最近项目中需要对生成的shp文件进行打包压缩成zip,gdal是可以直接操作zip、tar的,好像还不支持shp格式压缩(可能我的方式不对,如果可以希望网友指点),所有我是用zlib库来解决shp数据的压缩的。
因为我用的gdal是网上已经编译好的,已经包含了zlib库,所以直接使用,在配置环境的时候需要链接minizip.lib。
头文件如下:
extern "C"
{
#include "zlib.h"
#include "zip.h"
#include "unzip.h"
}
/**
* @brief 添加文件到zip
* @date 2020/03/12
* @return
* @param zf
* @param fileNameInZip
* @param srcFile
* @note
**/
void AddFileToZip(zipFile zf, const char* fileNameInZip, const char* srcFile)
{
FILE* srcfp = NULL;
//初始化写入zip的文件信息
zip_fileinfo zi;
zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
zi.dosDate = 0;
zi.internal_fa = 0;
zi.external_fa = 0;
//如果srcFile为空,加入空目录
char new_file_name[1204];
memset(new_file_name, 0, sizeof(new_file_name));
strcat(new_file_name, fileNameInZip);
if (srcFile == NULL)
{
strcat(new_file_name, "/");
}
//在zip文件中创建新文件
zipOpenNewFileInZip(zf, new_file_name, &zi, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION);
if (srcFile != NULL)
{
//打开源文件
srcfp = fopen(srcFile, "rb");
if (srcfp == NULL)
{
zipCloseFileInZip(zf); //关闭zip文件
return;
}
//读入源文件并写入zip文件
int size_buf = 0;
void* buf = NULL;
size_buf = 1024;
buf = (void*)malloc(size_buf);
int numBytes = 0;
while (!feof(srcfp))
{
numBytes = fread(buf, 1, size_buf, srcfp);
zipWriteInFileInZip(zf, buf, numBytes);
if (ferror(srcfp))
break;
}
//关闭源文件
fclose(srcfp);
}
//关闭zip文件
zipCloseFileInZip(zf);
}
最后是先把生成的shp文件添加到zip中,然后再删掉shp文件(期待更好的方案)。
CPLString pszDirPath = CPLGetDirname(pszFullPath);
CPLString pszZipPath = CPLFormFilename(pszDirPath, pszFBasename, "zip");
CPLString pszShpPath = CPLFormFilename(pszDirPath, pszFBasename, "shp");
CPLString pszDbfPath = CPLFormFilename(pszDirPath, pszFBasename, "dbf");
CPLString pszPrjPath = CPLFormFilename(pszDirPath, pszFBasename, "prj");
CPLString pszShxPath = CPLFormFilename(pszDirPath, pszFBasename, "shx");
CPLString pszShpName = CPLFormCIFilename("", pszFBasename, "shp");
CPLString pszDbfName = CPLFormCIFilename("", pszFBasename, "dbf");
CPLString pszPrjName = CPLFormCIFilename("", pszFBasename, "prj");
CPLString pszShxName = CPLFormCIFilename("", pszFBasename, "shx");
//#define APPEND_STATUS_CREATE (0) 不存在就创建,存在就截断(清空)
//#define APPEND_STATUS_CREATEAFTER (1) 不存在打开失败,存在就截断(清空)
//#define APPEND_STATUS_ADDINZIP (2) 不存在打开失败,存在就追加(原本压缩包中的内容不清空)
zipFile zf = zipOpen(pszZipPath, APPEND_STATUS_CREATE);
if (zf == NULL)
{
cout << "创建zip失败" << endl;
return -1;
}
AddFileToZip(zf, pszShpName, pszShpPath);
AddFileToZip(zf, pszDbfName, pszDbfPath);
AddFileToZip(zf, pszPrjName, pszPrjPath);
AddFileToZip(zf, pszShxName, pszShxPath);
zipClose(zf, 0);
//删除本地生成的shp文件
poDriver->Delete(pszFullPath);
上面代码压缩的zip,在解压时会出现下图的警告信息:
解决方法:
AddFileToZip函数在初始化写入zip信息的时候,是将时间都初始化为0,现在需要修改这个时间,如下:
time_t timep;
struct tm* p;
time(&timep);
//p = gmtime(&timep); // UTC时间
p = localtime(&timep); // 本地时间
//初始化写入zip的文件信息
zip_fileinfo zi;
zi.tmz_date.tm_year = 1900 + p->tm_yday;
zi.tmz_date.tm_mon = p->tm_mon;
zi.tmz_date.tm_mday = p->tm_mday;
zi.tmz_date.tm_hour = p->tm_hour;
zi.tmz_date.tm_min = p->tm_min;
zi.tmz_date.tm_sec = p->tm_sec;
//zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
// zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
zi.dosDate = 0;
zi.internal_fa = 0;
zi.external_fa = 0;