zlib minizip 压缩与解压缩

本文转自:http://blog.csdn.net/MulinB/article/details/6393139

本文转自:http://blog.csdn.net/tinyhum3d/article/details/7916264

本文转自:http://blog.csdn.net/wzq9706/article/details/6460656

 

注:如果对使用库没有限制的话,推荐使用另外的封装好的库更加方便,比如codeproject上可以找到的ZipUtils等(http://www.codeproject.com/KB/files/zip_utils.aspx)。

 

    使用zlib将文件夹压缩成zip文件时,需要自己读取文件然后写入zip文件。利用官方下载的zlib包中包含的contrib/minizip/zip.h和zip.c代码提供的函数,可以很容易实现这个功能。

    zip.h和zip.c函数接口介绍:
1. zipOpen  打开、创建zip文件
2. zipOpenNewFileInZip  在zip文件中创建新文件
3. zipWriteInFileInZip  将数据写入zip文件中的文件里
4. zipCloseFileInZip    关闭zip文件中的文件
5. zipClose  关闭zip文件

    在VC中将某个目录下的所有文件(包括子目录、空目录)压缩到一个zip文件中的代码如下:

 

  1. //code by MulinB  
  2. //2011-04-28  
  3.   
  4. #define UNICODE  
  5. #define _UNICODE  
  6.   
  7. #include <atlconv.h>  //for W2CA  
  8. #include "zlib/contrib/minizip/zip.h"  
  9.   
  10.   
  11. //最终接口:从某个目录创建zip文件  
  12. void CreateZipFromDir(const CString& dirName, const CString& zipFileName);  
  13.   
  14.   
  15. //将文件添加到zip文件中,注意如果源文件srcFile为空则添加空目录  
  16. //fileNameInZip: 在zip文件中的文件名,包含相对路径  
  17. void AddFileToZip(zipFile zf, const char* fileNameInZip, const char* srcFile)  
  18. {  
  19.   FILE* srcfp = NULL;  
  20.   
  21.   //初始化写入zip的文件信息  
  22.   zip_fileinfo zi;  
  23.   zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =  
  24.   zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;  
  25.   zi.dosDate = 0;  
  26.   zi.internal_fa = 0;  
  27.   zi.external_fa = 0;  
  28.   
  29.   //如果srcFile为空,加入空目录  
  30.   char new_file_name[MAX_PATH];  
  31.   memset(new_file_name, 0, sizeof(new_file_name));  
  32.   strcat(new_file_name, fileNameInZip);  
  33.   if (srcFile == NULL)  
  34.   {  
  35.       strcat(new_file_name, "/");  
  36.   }  
  37.     
  38.   //在zip文件中创建新文件  
  39.   zipOpenNewFileInZip(zf, new_file_name, &zi, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION);  
  40.   
  41.   if (srcFile != NULL)  
  42.   {  
  43.       //打开源文件  
  44.       srcfp = fopen(srcFile, "rb");  
  45.       if (srcfp == NULL)  
  46.       {  
  47.           MessageBox(_T("无法添加文件") + CString(srcFile) + _T("!"));  
  48.           zipCloseFileInZip(zf); //关闭zip文件  
  49.           return;  
  50.       }  
  51.   
  52.       //读入源文件并写入zip文件  
  53.       char buf[100*1024]; //buffer  
  54.       int numBytes = 0;  
  55.       while( !feof(srcfp) )  
  56.       {  
  57.           numBytes = fread(buf, 1, sizeof(buf), srcfp);  
  58.           zipWriteInFileInZip(zf, buf, numBytes);  
  59.           if( ferror(srcfp) )  
  60.               break;  
  61.       }  
  62.   
  63.       //关闭源文件  
  64.       fclose(srcfp);  
  65.   }  
  66.   
  67.   //关闭zip文件  
  68.   zipCloseFileInZip(zf);  
  69. }  
  70.   
  71.   
  72. //递归添加子目录到zip文件  
  73. void CollectFilesInDirToZip(zipFile zf, const CString& strPath, const CString& parentDir)  
  74. {  
  75.   USES_CONVERSION; //for W2CA  
  76.     
  77.   CString strRelativePath;  
  78.   CFileFind finder;   
  79.   BOOL bWorking = finder.FindFile(strPath + _T("//*.*"));  
  80.   while(bWorking)   
  81.   {   
  82.       bWorking = finder.FindNextFile();   
  83.       if(finder.IsDots())  
  84.           continue;   
  85.         
  86.       if (parentDir == _T(""))  
  87.           strRelativePath = finder.GetFileName();  
  88.       else  
  89.           strRelativePath = parentDir + _T("//") + finder.GetFileName(); //生成在zip文件中的相对路径  
  90.     
  91.       if(finder.IsDirectory())  
  92.       {  
  93.           AddFileToZip(zf, W2CA(strRelativePath), NULL); //在zip文件中生成目录结构  
  94.           CollectFilesInDirToZip(zf, finder.GetFilePath(), strRelativePath); //递归收集子目录文件  
  95.           continue;  
  96.       }  
  97.         
  98.       AddFileToZip(zf, W2CA(strRelativePath), W2CA(finder.GetFilePath())); //将文件添加到zip文件中  
  99.   }  
  100. }  
  101.   
  102.   
  103. //最终接口:从某个目录创建zip文件  
  104. void CreateZipFromDir(const CString& dirName, const CString& zipFileName)  
  105. {  
  106.   USES_CONVERSION; //使用W2CA转换unicode字符集  
  107.   zipFile newZipFile = zipOpen(W2CA(zipFileName), APPEND_STATUS_CREATE); //创建zip文件  
  108.   if (newZipFile == NULL)  
  109.   {  
  110.     MessageBox(_T("无法创建zip文件!"));  
  111.     return;  
  112.   }  
  113.     
  114.   CollectFilesInDirToZip(newZipFile, dirName, _T(""));  
  115.   zipClose(newZipFile, NULL); //关闭zip文件  
  116. }  

-----------------------------------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------------------------------

 

1、unzOpen(filePath)


这个方法可以打开一个压缩文件,返回一个句柄,这个句柄将在后面的方法中被用到。


2、unzGetGlobalInfo()


这个可以得到全局的信息。常用的是压缩包里的文件个数。


3、unzGotoFirstFile()


定位到压缩文件中的第一个文件。


    3.1 unzGetCurrentFileInfo() 

    得到相关的文件信息。

    

     注意:

     a) zlib在压缩过程通过名字后最后一个字符是'/',来解决文件是文件还是文件夹的问题。但内部只是说明了层级关系。没有folder的属性。所以,在zlib里,一切皆文件。

     b) 是不是folder,压缩者和解压者是通过上述文件信息中的一个可以自己定义的数据部分,来决定一个读出来的file是否是folder。


    3.2 如果是文件夹,通过各个平台的接口创建出文件夹。

    

    3.3 如果是文件,zlib给出的info里面,是一个基于最初的folder的根目录的层级性的路径。

    a) 装配好整个文件路径,创建出文件;


    3.4 unzOpenCurrentFile()

    打开当前定位的压缩包中的文件。


    3.5 unzReadCurrentFile()

    从当前压缩包中开始读文件,可以告知这个方法buffer的大小,然后不停的循环,直到这个方法返回的值为0。在每个循环中间,把读出的数据送入3.3.a中创建的文件。


    3.6 unzCloseCurrentFile()

    关闭这个文件。


4、unzGotoNextFile()

定位到下一个文件。


整个解压缩的循环大致如此。


------------------------------------------------

1、zipOpen(),这里打开一个文件,这个文件就是最后所有压缩数据的载体。


对于zlib的zip过程来说,本身并没有所谓的folder和file之说。对于压缩一个或者一些文件来说,就是简单的用zip的newfile接口,打开、写入、关闭。但是,对于我们常看到的对一个目录的压缩,我们在根本上还是用zip的new file接口,但是要注意到送入zip在层级关系上对所谓的目录的支持。


对于一个文件来说,用


2、zipOpenNewFileInZip() 在压缩句柄中创建出一个文件,注意,文件名是有讲究的:最后一个字符不是/。


对于一个文件夹来说,也是用上面的接口创建一个文件,不过,最后一个字符是 /。 别用'\' ,用上反斜杠,层级还是对的,但是会在每个目录下多出来一个小文件,而且小文件是个无效文件(用winrar打开看的到,但解压就看不到)。


对于文件夹下面的文件和文件夹,送入上面的接口的参数中,第二个参数,必须是带层级关系的。从根目录开始的层级。这样压缩出来的结果才能保持原来的层级关系。


3、zipCloseFileInZip()


每个文件(文件夹),一旦要写的数据写完了,就需要用这个方法来关闭。


4、zipWriteInFileInZip()


这个方法对压缩文件当前文件写入文件内容

 

-----------------------------------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------------------------------

 

先上代码,压缩包的文件结构解析:
 

  函数功能可以通过函数名了解到。这里只说下:

  unzGetCurrentFileInfo(zip, &file_info, szZipName, sizeof(szZipName), NULL, 0, NULL, 0);获取当前文件信息并保存到file_info结构体中。

  unzGetCurrentFileID(zip, &dwFileNum, &dwFilePos);得到当前文件在压缩包中的位置信息。第二个参数是该压缩包到这个文件时已有的文件数(可以理解为到文件头的偏移),第三个参数就是文件的位置。可以保存这两个参数,方便以后打开该压缩包后,直接跳转到该文件。

  需要注意的是文件夹的相对路径也会作为一个szFileName,与文件类似。即如果有data/user.dat,Zlib会读成两个:data/、data/user.dat。

 

  下面说下压缩包中文件的读取。代码如下:

  unzGoToFileID(zip, pFPI->dwFileNum, pFPI->dwFilePos);即根据上面提到的文件数(文件偏移)和文件位置,跳转到该文件。

  unzOpenCurrentFilePassword(zip, resItem->password[0] ? resItem->password : 0)打开该文件,第二个参数即压缩包密码,没有密码就设为0。

  unzReadCurrentFile(zip, ptr, file_info.uncompressed_size)读取文件内容了。

  详细使用方法请参考代码

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值