使用GDAL的vsizip虚拟文件系统写入GeoTIFF至Zip文件报错求助
解决GDAL vsizip写入GeoTIFF时的报错问题
嘿,我来帮你搞定这两个GDAL使用vsizip时的错误!先拆解一下你遇到的两个问题:
错误原因分析
- 路径格式错误:你写的
/vsizip:\Projects\oy_vey.zip\my.tif格式不对,Windows下vsizip的正确路径格式应该是/vsizip/C:/Projects/oy_vey.zip/my.tif——要把盘符放在/vsizip后面,全程用正斜杠(/)分隔,不能用反斜杠(\),也不能把盘符冒号跟在vsizip后面。这个格式问题直接导致GDAL找不到正确的归档路径,触发了No such file or directory错误。 - 随机访问限制:GeoTIFF驱动写入时需要随机访问文件(比如seek操作),但vsizip的可写流是顺序的,不支持随机写入,所以直接创建zip里的TIFF文件会触发
Random access not supported错误。
具体解决方案
核心思路是:先把GeoTIFF写入内存虚拟文件(/vsimem/),再把内存文件复制到zip归档中。这样既避开了vsizip的随机访问限制,又能正确写入zip。
步骤1:初始化GDAL并写入GeoTIFF到内存
首先要注册GDAL驱动,然后创建内存虚拟文件并写入数据:
#include "gdal.h" #include "gdal_priv.h" #include "cpl_conv.h" #include "cpl_vsi.h" int main() { // 初始化GDAL GDALAllRegister(); // 开启虚拟文件缓存,优化内存文件操作 CPLSetConfigOption("GDAL_VSI_CACHE", "TRUE"); // 1. 写入GeoTIFF到内存虚拟文件 const char* vsimemPath = "/vsimem/temp_tiff.tif"; GDALDriver* tiffDriver = GetGDALDriverManager()->GetDriverByName("GTiff"); if (!tiffDriver) { printf("GTiff驱动加载失败!\n"); return 1; } // 假设创建一个100x100的单波段Byte类型TIFF(根据你的需求调整参数) int width = 100; int height = 100; int bands = 1; GDALDataset* dstDS = tiffDriver->Create(vsimemPath, width, height, bands, GDT_Byte, NULL); if (!dstDS) { printf("内存虚拟文件创建失败!\n"); return 1; } // 设置地理信息(根据你的数据调整) double geoTransform[6] = {0.0, 1.0, 0.0, 0.0, 0.0, -1.0}; // 左上角坐标、分辨率等 dstDS->SetGeoTransform(geoTransform); const char* projectionWKT = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]"; dstDS->SetProjection(projectionWKT); // 写入像素数据(这里模拟填充全255的白色数据) GDALRasterBand* rasterBand = dstDS->GetRasterBand(1); unsigned char* pixelData = new unsigned char[width * height]; memset(pixelData, 255, width * height); rasterBand->RasterIO(GF_Write, 0, 0, width, height, pixelData, width, height, GDT_Byte, 0, 0); // 关闭数据集,确保内存文件写入完成 GDALClose(dstDS); delete[] pixelData;
步骤2:将内存文件复制到Zip归档
接下来用GDAL的虚拟文件操作函数,把内存里的TIFF复制到目标Zip中:
// 2. 复制内存文件到Zip(注意Windows下的正确路径格式) const char* zipOutputPath = "/vsizip/C:/Projects/oy_vey.zip/my.tif"; if (VSICopyFile(vsimemPath, zipOutputPath, FALSE) != 0) { printf("复制到Zip失败!\n"); VSIUnlink(vsimemPath); // 清理内存文件 return 1; } // 清理内存虚拟文件 VSIUnlink(vsimemPath); printf("成功将GeoTIFF写入Zip!\n"); return 0; }
额外注意事项
- 确保你的GDAL版本在2.0以上,较新的版本对vsizip的写入支持更稳定。
- 如果目标Zip归档不存在,
VSICopyFile会自动创建它,不需要提前手动创建Zip。 - 要是需要往同一个Zip里写入多个文件,只需要重复复制步骤,路径写成
/vsizip/C:/Projects/oy_vey.zip/another_file.tif即可。
内容的提问来源于stack exchange,提问作者Felix
相关产品推荐
相关产品推荐

