【VC++技術雜談008】使用zlib解壓zip壓縮文件

  最近由於項目的須要,要對zip壓縮文件進行批量解壓。在網上查閱了相關的資料後,最終使用zlib開源庫實現了該功能。本文將對zlib開源庫進行簡單介紹,並給出一個使用zlib開源庫對zip壓縮文件進行解壓的示例程序。算法

 

1.zlib開源庫函數

  zlib是應用最普遍的壓縮與解壓縮zip文件的免費開源庫,提供了數據壓縮與解壓縮的函式庫。spa

  zlib中最關鍵的函數有如下兩個:code

  (1)int compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);blog

  (2)int uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);ip

  其中,函數compress()用於將源緩衝區數據壓縮到目的緩衝區,函數uncompress()用於將源緩衝區數據解壓到目的緩衝區。內存

  因而可知,zlib只是一個針對gzip以及deflate算法的庫,用於將一段內存壓縮/解壓以後放到另外一段內存上,這離壓縮/解壓文件甚至文件夾的目標還很遠。可是,它提供了一個叫作minizip的例子給出了操做zip文件的方法。博客

 

2.minizip簡介it

  minizip是zlib的上層庫,它封裝了與zip文件相關的操做。io

  minizip中與解壓縮相關的API有如下幾個:

  (1)unzFile unzOpen(const char *path); 

  (2)int unzClose(unzFile file);

  (3)int unzGetGlobalInfo(unzFile file, unz_global_info *pglobal_info);

  (4)int unzGoToNextFile(unzFile file);

  (5)int unzGetCurrentFileInfo(unzFile file, unz_file_info *pfile_info, char *szFileName, uLong fileNameBufferSize, 

void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize);

  (6)int unzOpenCurrentFile(unzFile file);

  (7)int unzCloseCurrentFile(unzFile file);

  (8)int unzReadCurrentFile(unzFile file, voidp buf, unsigned len);

  有了以上這些API,咱們就能夠對zip文件進行解壓縮了。一個完整的解壓過程應該包含如下這些步驟:

  (1)調用unzOpen()函數打開一個zip壓縮文件,其參數是zip壓縮文件的路徑。

  (2)調用unzGetGlobalInfo()函數來獲取zip壓縮文件的一些信息(如內部文件個數等),這些信息會保存在傳入參數pglobal_info中。

  (3)而後開始遍歷zip文件中的內部文件,初始時會自動定位到第一個內部文件,處理完一個內部文件後可使用unzGoToNextFile()函數來跳轉到下一個內部文件。

  (4)對於每一個內部文件來講,能夠先調用unzGetCurrentFileInfo()函數來獲取該內部文件信息(如文件的路徑、文件大小等),這些信息會保存在傳入參數pfile_info中。

  (5)調用unzOpenCurrentFile()函數打開該內部文件。

  (6)調用unzReadCurrentFile()函數讀取該內部文件內容。

  (7)該內部文件讀取完畢以後,調用unzCloseCurrentFile()函數對內部文件進行關閉。

  (8)zip文件中的全部內部文件遍歷完成以後,調用unzClose()函數關閉打開的zip壓縮文件。

 

3.示例程序

  瞭解了以上的內容以後,咱們就能夠編寫程序使用zlib以及minizip對zip壓縮文件進行解壓縮了。

3.1加載相關的頭文件及庫文件

  在使用zlib以及minizip以前,咱們須要加載相關的頭文件及庫文件到工程中。須要加載的頭文件有zlib.h、unzip.h、zip.h。須要加載的庫文件有zlib.lib、minizip.lib。須要添加的動態連接庫zlib1.dll。這些文件均可以從網上下載獲得。

1     #include "zlib/zlib.h"
2     #include "zlib/unzip.h"
3     #include "zlib/zip.h"
4     #pragma comment(lib, "zlib.lib")
5     #pragma comment(lib, "minizip.lib")

3.2配置工程

  由於zlib以及minizip是用C語言編寫的,在VC6.0中使用時,須要對工程進行以下配置,不然會出現編譯連接通不過的問題。

  (1)在「工程」、「設置」中選擇「鏈接」標籤頁,在「分類」中選擇輸入,在「忽略庫」中加入MSVCRT。

  (2)在「工程」、「設置」中選擇「C/C++」標籤頁,在「分類」中選擇Code Generation,在「Use run-time library」中選擇「Debug Multithreaded DLL」。

  (3)在「工程」、「設置」中選擇「C/C++」標籤頁,在「分類」中選擇常規,在「預處理程序定義」中加入_AFXDLL。

3.3示例程序

  以下的示例程序演示瞭如何調用minizip中的API對zip文件進行解壓。

  1 /*
  2  * 函數功能 :  解壓zip文件
  3  * 備    注 : 參數strFilePath表示zip壓縮文件的路徑
  4  *           參數strTempPath表示要解壓到的文件目錄
  5  * 做    者 : 博客園 依舊淡然(http://www.cnblogs.com/menlsh/  6  */
  7 void CZlibDemoDlg::UnzipFile(CString strFilePath, CString strTempPath)
  8 {
  9     int nReturnValue;
 10 
 11     //打開zip文件
 12     unzFile unzfile = unzOpen(strFilePath);                    
 13     if(unzfile == NULL)
 14     {
 15         MessageBox("打開zip文件失敗!", "提示", MB_OK|MB_ICONWARNING);
 16         return;
 17     }
 18 
 19     //獲取zip文件的信息
 20     unz_global_info* pGlobalInfo = new unz_global_info;
 21     nReturnValue = unzGetGlobalInfo(unzfile, pGlobalInfo);
 22     if(nReturnValue != UNZ_OK)
 23     {
 24         MessageBox("獲取zip文件信息失敗!", "提示", MB_OK|MB_ICONWARNING);
 25         return;
 26     }
 27 
 28     //解析zip文件
 29     unz_file_info* pFileInfo = new unz_file_info;
 30     char szZipFName[MAX_PATH];                            //存放從zip中解析出來的內部文件名
 31     for(int i=0; i<pGlobalInfo->number_entry; i++)
 32     {
 33         //解析獲得zip中的文件信息
 34         nReturnValue = unzGetCurrentFileInfo(unzfile, pFileInfo, szZipFName, MAX_PATH, 
 35             NULL, 0, NULL, 0);
 36         if(nReturnValue != UNZ_OK)
 37         {
 38             MessageBox("解析zip文件信息失敗!", "提示", MB_OK|MB_ICONWARNING);
 39             return;
 40         }
 41 
 42         //判斷是文件夾仍是文件
 43         switch(pFileInfo->external_fa)
 44         {
 45         case FILE_ATTRIBUTE_DIRECTORY:                    //文件夾
 46             {
 47                 CString strDiskPath = strTempPath + _T("//") + szZipFName;
 48                 CreateDirectory(strDiskPath, NULL);
 49             }
 50             break;
 51         default:                                        //文件
 52             {
 53                 //建立文件
 54                 CString strDiskFile = strTempPath + _T("//") + szZipFName;
 55                 HANDLE hFile = CreateFile(strDiskFile, GENERIC_WRITE,
 56                     0, NULL, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
 57                 if(hFile == INVALID_HANDLE_VALUE)
 58                 {
 59                     MessageBox("建立文件失敗!", "提示", MB_OK|MB_ICONWARNING);
 60                     return;
 61                 }
 62 
 63                 //打開文件
 64                 nReturnValue = unzOpenCurrentFile(unzfile);
 65                 if(nReturnValue != UNZ_OK)
 66                 {
 67                     MessageBox("打開文件失敗!", "提示", MB_OK|MB_ICONWARNING);
 68                     CloseHandle(hFile);
 69                     return;
 70                 }
 71 
 72                 //讀取文件
 73                 const int BUFFER_SIZE = 4096;
 74                 char szReadBuffer[BUFFER_SIZE];
 75                 while(TRUE)
 76                 {
 77                     memset(szReadBuffer, 0, BUFFER_SIZE);
 78                     int nReadFileSize = unzReadCurrentFile(unzfile, szReadBuffer, BUFFER_SIZE);
 79                     if(nReadFileSize < 0)                //讀取文件失敗
 80                     {
 81                         MessageBox("讀取文件失敗!", "提示", MB_OK|MB_ICONWARNING);
 82                         unzCloseCurrentFile(unzfile);
 83                         CloseHandle(hFile);
 84                         return;
 85                     }
 86                     else if(nReadFileSize == 0)            //讀取文件完畢
 87                     {
 88                         unzCloseCurrentFile(unzfile);
 89                         CloseHandle(hFile);
 90                         break;
 91                     }
 92                     else                                //寫入讀取的內容
 93                     {
 94                         DWORD dWrite = 0;
 95                         BOOL bWriteSuccessed = WriteFile(hFile, szReadBuffer, BUFFER_SIZE, &dWrite, NULL);
 96                         if(!bWriteSuccessed)
 97                         {
 98                             MessageBox("讀取文件失敗!", "提示", MB_OK|MB_ICONWARNING);
 99                             unzCloseCurrentFile(unzfile);
100                             CloseHandle(hFile);
101                             return;
102                         }
103                     }
104                 }
105             }
106             break;
107         }
108         unzGoToNextFile(unzfile);
109     }
110 
111     //關閉
112     if(unzfile)
113     {
114         unzClose(unzfile);
115     }
116 }

3.4運行結果

  調用上述的UnzipFile()方法對某個zip文件進行解壓,如圖1所示。

圖1 解壓zip文件

  解壓後,能夠看到文件夾123中的內容如圖2所示。

圖2 解壓後的文件

相關文章
相關標籤/搜索