2012-05-03 76 views
29

有沒有簡單的如何解壓縮.zip文件並將文件解壓到目錄的例子?我目前使用zlib,雖然我知道zlib並不直接處理zip文件,但在zlibs的「contrib」庫中似乎還有其他一些東西。我注意到並閱讀了「minizip」,在閱讀了一些文檔並查看了一些代碼後,我沒有看到一個簡單的例子,即如何解壓縮.zip文件並將這些文件解壓縮到目錄。使用zlib解壓縮.zip文件的簡單方法

我想找到一個平臺獨立的方式來做到這一點,但如果這是不可能的,那麼我需要找到一個Windows和Mac的方式。

+3

爲讀者尋找如何做相反的事情 - 使用zlib的創建一個zip文件,看到我的答案在這裏: http://stackoverflow.com/questions/11370908/how-do-i-use-minizip-on-zlib – niemiro

回答

41

zlib處理deflate壓縮/解壓縮算法,但在ZIP文件中不止這些。

您可以嘗試libzip。它是免費的,便攜式和易於使用。

更新:在這裏,我附上libzip的quick'n'dirty例如,所有的錯誤控制中省略:

#include <zip.h> 

int main() 
{ 
    //Open the ZIP archive 
    int err = 0; 
    zip *z = zip_open("foo.zip", 0, &err); 

    //Search for the file of given name 
    const char *name = "file.txt"; 
    struct zip_stat st; 
    zip_stat_init(&st); 
    zip_stat(z, name, 0, &st); 

    //Alloc memory for its uncompressed contents 
    char *contents = new char[st.size]; 

    //Read the compressed file 
    zip_file *f = zip_fopen(z, name, 0); 
    zip_fread(f, contents, st.size); 
    zip_fclose(f); 

    //And close the archive 
    zip_close(z); 

    //Do something with the contents 
    //delete allocated memory 
    delete[] contents; 
} 
+2

你能否提供一個簡單的例子來說明如何使用libzip解壓文件? – judeclarke

+0

沒問題。查看更新後的答案。 – rodrigo

+0

經過幾天與libzip摔跤,讓它在Windows上編譯,事實證明你的文章中的代碼不會編譯。 zip_stat是一個函數,而不是像你提到的類型 – judeclarke

25

Minizip確實有一個例子程序來演示其使用 - 文件被稱爲minizip.c和miniunz.c。

更新:我有幾分鐘的時間,所以我爲你提供了這個快速,純粹的骨頭例子。這是非常臭C,我不會使用它沒有重大改進。希望現在就足夠讓你去。

// uzip.c - Simple example of using the minizip API. 
// Do not use this code as is! It is educational only, and probably 
// riddled with errors and leaks! 
#include <stdio.h> 
#include <string.h> 

#include "unzip.h" 

#define dir_delimter '/' 
#define MAX_FILENAME 512 
#define READ_SIZE 8192 

int main(int argc, char **argv) 
{ 
    if (argc < 2) 
    { 
     printf("usage:\n%s {file to unzip}\n", argv[ 0 ]); 
     return -1; 
    } 

    // Open the zip file 
    unzFile *zipfile = unzOpen(argv[ 1 ]); 
    if (zipfile == NULL) 
    { 
     printf("%s: not found\n"); 
     return -1; 
    } 

    // Get info about the zip file 
    unz_global_info global_info; 
    if (unzGetGlobalInfo(zipfile, &global_info) != UNZ_OK) 
    { 
     printf("could not read file global info\n"); 
     unzClose(zipfile); 
     return -1; 
    } 

    // Buffer to hold data read from the zip file. 
    char read_buffer[ READ_SIZE ]; 

    // Loop to extract all files 
    uLong i; 
    for (i = 0; i < global_info.number_entry; ++i) 
    { 
     // Get info about current file. 
     unz_file_info file_info; 
     char filename[ MAX_FILENAME ]; 
     if (unzGetCurrentFileInfo(
      zipfile, 
      &file_info, 
      filename, 
      MAX_FILENAME, 
      NULL, 0, NULL, 0) != UNZ_OK) 
     { 
      printf("could not read file info\n"); 
      unzClose(zipfile); 
      return -1; 
     } 

     // Check if this entry is a directory or file. 
     const size_t filename_length = strlen(filename); 
     if (filename[ filename_length-1 ] == dir_delimter) 
     { 
      // Entry is a directory, so create it. 
      printf("dir:%s\n", filename); 
      mkdir(filename); 
     } 
     else 
     { 
      // Entry is a file, so extract it. 
      printf("file:%s\n", filename); 
      if (unzOpenCurrentFile(zipfile) != UNZ_OK) 
      { 
       printf("could not open file\n"); 
       unzClose(zipfile); 
       return -1; 
      } 

      // Open a file to write out the data. 
      FILE *out = fopen(filename, "wb"); 
      if (out == NULL) 
      { 
       printf("could not open destination file\n"); 
       unzCloseCurrentFile(zipfile); 
       unzClose(zipfile); 
       return -1; 
      } 

      int error = UNZ_OK; 
      do  
      { 
       error = unzReadCurrentFile(zipfile, read_buffer, READ_SIZE); 
       if (error < 0) 
       { 
        printf("error %d\n", error); 
        unzCloseCurrentFile(zipfile); 
        unzClose(zipfile); 
        return -1; 
       } 

       // Write data to file. 
       if (error > 0) 
       { 
        fwrite(read_buffer, error, 1, out); // You should check return of fwrite... 
       } 
      } while (error > 0); 

      fclose(out); 
     } 

     unzCloseCurrentFile(zipfile); 

     // Go the the next entry listed in the zip file. 
     if ((i+1) < global_info.number_entry) 
     { 
      if (unzGoToNextFile(zipfile) != UNZ_OK) 
      { 
       printf("cound not read next file\n"); 
       unzClose(zipfile); 
       return -1; 
      } 
     } 
    } 

    unzClose(zipfile); 

    return 0; 
} 

我建立和使用MinGW/MSYS測試它在Windows這樣的:

contrib/minizip/$ gcc -I../.. -o unzip uzip.c unzip.c ioapi.c ../../libz.a 
contrib/minizip/$ ./unzip.exe /j/zlib-125.zip 
+0

我以前看過那個例子,這是一個很大的例子。有沒有更簡單的例子可以提供? – judeclarke

+0

@judeclarke,我今天離開了我的開發箱,但我會盡可能地發佈更小/更簡單的東西! –

+5

您只需花時間閱讀頭文件和示例。首先查看zip.h和unzip.h,看看提供的功能以及它們的功能。然後看看minizip.c和miniunz.c,看看它們是如何使用的。 –