[Zlib]_[初级]_[使用zlib库压缩文件]

来源:互联网 发布:db2和sql server 编辑:程序博客网 时间:2024/05/16 15:13

场景:

1. WIndows上没找到系统提供的win32 api来生成zip压缩文件, 有知道的大牛麻烦留个言。

2. zlib比较常用,编译也方便,使用它来做压缩吧。MacOSX平台默认支持zlib库.

http://zlib.net

3. zlib库里的 src\contrib\minizip\minizip.c  里有压缩例子, 我现在使用的是zlib 1.2.5,用vs2010编译完。下载地址:

http://download.csdn.net/detail/infoworld/8177625

4. 自己封装了一下ZipHelper便于使用,首先先得编译zlib为dll版本, 这个类就是删减了minizip.c的一些东西, 支持中文路径,项目需要目前只支持一级目录,如果有子目录的也不难,自己改改吧。

5. 使用方式, 注意, 路径字符串必须是utf8格式编码, 编译时要加上预编译宏 ZLIB_WINAPI

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. ZipHelper z;  
  2. z.AddFile(utf8_path1);  
  3. z.AddFile(utf8_path2);  
  4. z.ToZip(utf8_output_zip_path);  

6. MacOSX没测过,理论上应该可以编译过。

zip_helper.h

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #ifndef __ZIP_HELPER  
  2. #define __ZIP_HELPER  
  3.   
  4. #include <vector>  
  5. #include <string>  
  6.   
  7. //1.暂时不支持子目录  
  8. //注意: 因为使用了zlib库,使用时加上预编译宏 ZLIB_WINAPI  
  9. class ZipHelper  
  10. {  
  11. public:  
  12.     ZipHelper(){}  
  13.     ~ZipHelper(){}  
  14.   
  15.     //path: utf8 path  
  16.     ZipHelper& AddFile(const char* input_path);  
  17.     //output_path :utf8 path  
  18.     bool ToZip(const char* output_path);  
  19.   
  20. private:  
  21.     std::vector<std::string> files_;  
  22. };  
  23.   
  24.   
  25. #endif  

zip_helper.cpp

[cpp] view plain copy
  1. #include "zip_helper.h"  
  2.   
  3.   
  4. #ifndef _WIN32  
  5. #ifndef __USE_FILE_OFFSET64  
  6. #define __USE_FILE_OFFSET64  
  7. #endif  
  8. #ifndef __USE_LARGEFILE64  
  9. #define __USE_LARGEFILE64  
  10. #endif  
  11. #ifndef _LARGEFILE64_SOURCE  
  12. #define _LARGEFILE64_SOURCE  
  13. #endif  
  14. #ifndef _FILE_OFFSET_BIT  
  15. #define _FILE_OFFSET_BIT 64  
  16. #endif  
  17. #endif  
  18.   
  19. #include <stdio.h>  
  20. #include <stdlib.h>  
  21. #include <string.h>  
  22. #include <time.h>  
  23. #include <errno.h>  
  24. #include <fcntl.h>  
  25.   
  26. #include <direct.h>  
  27. #include <io.h>  
  28.   
  29. #include "zlib.h"  
  30.   
  31. #include "zip.h"  
  32.   
  33. #ifdef _WIN32  
  34. #define USEWIN32IOAPI  
  35. #include "iowin32.h"  
  36. #endif  
  37.   
  38. #define WRITEBUFFERSIZE (16384)  
  39. #define MAXFILENAME (256)  
  40.   
  41.   
  42.   
  43.   
  44. #ifdef _WIN32  
  45.   
  46. static char* Utf8ToAnsi(const char* utf8)    
  47. {    
  48.     // 先转换为UNICODE  
  49.     int dwUnicodeLen = MultiByteToWideChar(CP_UTF8,0,utf8,-1,NULL,0);    
  50.     if(!dwUnicodeLen)    
  51.     {    
  52.         return strdup(utf8);    
  53.     }    
  54.     size_t num = dwUnicodeLen*sizeof(wchar_t);    
  55.     wchar_t *pwText = (wchar_t*)malloc(num+2);    
  56.     memset(pwText,0,num+2);    
  57.     MultiByteToWideChar(CP_UTF8,0,utf8,-1,pwText,dwUnicodeLen);  
  58.       
  59.     // 再转换为ANSI  
  60.     int len;    
  61.     len = WideCharToMultiByte(CP_ACP, 0, pwText, -1, NULL, 0, NULL, NULL);    
  62.     char *szANSI = (char*)malloc(len + 1);    
  63.     memset(szANSI, 0, len + 1);    
  64.     WideCharToMultiByte(CP_ACP, 0, pwText, -1, szANSI, len, NULL,NULL);    
  65.   
  66.     free(pwText);  
  67.     return (char*)szANSI;    
  68. }   
  69.   
  70. static wchar_t* QXUtf82Unicode(const char* utf)    
  71. {    
  72.     if(!utf || !strlen(utf))    
  73.     {    
  74.         return NULL;    
  75.     }    
  76.     int dwUnicodeLen = MultiByteToWideChar(CP_UTF8,0,utf,-1,NULL,0);    
  77.     size_t num = dwUnicodeLen*sizeof(wchar_t);    
  78.     wchar_t *pwText = (wchar_t*)malloc(num);    
  79.     memset(pwText,0,num);    
  80.     MultiByteToWideChar(CP_UTF8,0,utf,-1,pwText,dwUnicodeLen);    
  81.     return pwText;    
  82. }   
  83.   
  84. static FILE* ZipFopen(const char* path,const char* mode)  
  85. {  
  86.     wchar_t* path_u = QXUtf82Unicode(path);  
  87.     wchar_t* mode_u = QXUtf82Unicode(mode);  
  88.     FILE* file = _wfopen(path_u,mode_u);  
  89.     free(path_u);  
  90.     free(mode_u);  
  91.     return file;  
  92. }  
  93.   
  94. /* name of file to get info on */  
  95. /* return value: access, modific. and creation times */  
  96. /* dostime */  
  97. uLong filetime(const char* f, tm_zip *tmzip, uLong *dt)            
  98. {  
  99.     int ret = 0;  
  100.     {  
  101.         FILETIME ftLocal;  
  102.         HANDLE hFind;  
  103.         WIN32_FIND_DATA ff32;  
  104.         wchar_t *unicode = QXUtf82Unicode(f);  
  105.         hFind = FindFirstFile(unicode,&ff32);  
  106.         if (hFind != INVALID_HANDLE_VALUE)  
  107.         {  
  108.             FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);  
  109.             FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);  
  110.             FindClose(hFind);  
  111.             ret = 1;  
  112.         }  
  113.         free(unicode);  
  114.     }  
  115.     return ret;  
  116. }  
  117. #else  
  118. #define ZipFopen fopen;  
  119. #endif  
  120.   
  121. ZipHelper& ZipHelper::AddFile(const char* input_path)  
  122. {  
  123.     files_.push_back(input_path);  
  124.     return *this;  
  125. }  
  126.   
  127. bool ZipHelper::ToZip(const char* output_path)  
  128. {  
  129.     int err=0;  
  130.     zipFile zf;  
  131.     int errclose;  
  132.     int opt_compress_level = Z_DEFAULT_COMPRESSION;  
  133. #ifdef USEWIN32IOAPI  
  134.     zlib_filefunc64_def ffunc;  
  135.     fill_win32_filefunc64W(&ffunc);  
  136.     wchar_t* temp_path = QXUtf82Unicode(output_path);  
  137.     zf = zipOpen2_64(temp_path,APPEND_STATUS_CREATE,NULL,&ffunc);  
  138.     free(temp_path);  
  139. #else  
  140.     zf = zipOpen64(output_path,APPEND_STATUS_CREATE);  
  141. #endif  
  142.   
  143.     if (zf == NULL)  
  144.     {  
  145.         printf("error opening %s\n",output_path);  
  146.         err= ZIP_ERRNO;  
  147.         return false;  
  148.     }  
  149.   
  150.     int size = files_.size();  
  151.     void* buf = NULL;  
  152.     int size_buf = WRITEBUFFERSIZE;  
  153.     buf = (void*)malloc(size_buf);  
  154.     for (int i = 0; i < size; ++i)  
  155.     {  
  156.         FILE * fin;  
  157.         int size_read;  
  158.         const char* filenameinzip = files_[i].c_str();  
  159.         const char *savefilenameinzip;  
  160.         zip_fileinfo zi;  
  161.         unsigned long crcFile=0;  
  162.         int zip64 = 0;  
  163.   
  164.         zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =  
  165.             zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;  
  166.         zi.dosDate = 0;  
  167.         zi.internal_fa = 0;  
  168.         zi.external_fa = 0;  
  169.         filetime(filenameinzip,&zi.tmz_date,&zi.dosDate);  
  170.   
  171.         savefilenameinzip = filenameinzip;  
  172.         const char* pos = NULL;  
  173.           
  174.         if( (pos = strrchr(savefilenameinzip,'\\'))   
  175.             || (pos = strrchr(savefilenameinzip,'/')) )  
  176.         {  
  177.             pos++;  
  178.         }else  
  179.         {  
  180.             pos = savefilenameinzip;  
  181.         }  
  182.         // 这个版本不支持UTF8字符串的正确存储,所以要转换为ANSI显示.  
  183.         char* pos_ansi = Utf8ToAnsi(pos);  
  184.         err = zipOpenNewFileInZip3_64(zf,pos_ansi,&zi,  
  185.             NULL,0,NULL,0,NULL,  
  186.             (opt_compress_level != 0) ? Z_DEFLATED : 0,  
  187.             opt_compress_level,0,  
  188.             -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,  
  189.             NULL,crcFile, zip64);  
  190.         free(pos_ansi);  
  191.   
  192.         if (err != ZIP_OK)  
  193.         {  
  194.             printf("error in opening %s in zipfile\n",pos);  
  195.         }  
  196.         else  
  197.         {  
  198.             fin = ZipFopen(filenameinzip,"rb");  
  199.             if (fin==NULL)  
  200.             {  
  201.                 err=ZIP_ERRNO;  
  202.                 printf("error in opening %s for reading\n",filenameinzip);  
  203.             }  
  204.         }  
  205.   
  206.         if (err == ZIP_OK)  
  207.             do  
  208.             {  
  209.                 err = ZIP_OK;  
  210.                 size_read = (int)fread(buf,1,size_buf,fin);  
  211.                 if (size_read < size_buf)  
  212.                 {  
  213.                     if (feof(fin)==0)  
  214.                     {  
  215.                         printf("error in reading %s\n",filenameinzip);  
  216.                         err = ZIP_ERRNO;  
  217.                     }  
  218.                 }  
  219.                 if (size_read>0)  
  220.                 {  
  221.                     err = zipWriteInFileInZip (zf,buf,size_read);  
  222.                     if (err<0)  
  223.                     {  
  224.                         printf("error in writing %s in the zipfile\n",  
  225.                             filenameinzip);  
  226.                     }  
  227.                 }  
  228.             } while ((err == ZIP_OK) && (size_read>0));  
  229.   
  230.             if(fin)  
  231.             {  
  232.                 fclose(fin);  
  233.             }  
  234.   
  235.             if (err<0)  
  236.             {  
  237.                 err=ZIP_ERRNO;  
  238.             }  
  239.             else  
  240.             {  
  241.                 err = zipCloseFileInZip(zf);  
  242.                 if (err!=ZIP_OK)  
  243.                 {  
  244.                     printf("error in closing %s in the zipfile\n",filenameinzip);  
  245.                 }  
  246.   
  247.             }  
  248.     }  
  249.     errclose = zipClose(zf,NULL);  
  250.     if (errclose != ZIP_OK)  
  251.     {  
  252.         printf("error in closing %s\n",output_path);  
  253.         return false;  
  254.     }  
  255.     return true;  
  256. }  

注意: 再链接项目时如果报错, 那么就是因为你没加预编译宏 ZLIB_WINAPI

[plain] view plain copy
  1. 1>zip_helper.obj : error LNK2001: 无法解析的外部符号 _zipClose  

完整项目下载地址:

http://download.csdn.net/detail/infoworld/9482396 (1.1 解决中文名在zip里的显示问题)

0 0