2012-02-15 40 views
1

我正在構建一個應用程序,它需要在不提取文件的情況下讀取zip文件內的文件。有沒有這種功能的圖書館,或者你能給我一些關於如何解決它的想法嗎?是否可以在不提取Objective-C文件的情況下讀取壓縮文件?

+2

如果你能讀一個壓縮文件,解壓沒有它,就不會有任何點在解壓所有,你不覺得嗎?文件將被永久壓縮。 – EmilioPelaez 2012-02-15 08:12:27

+3

@EmilioPelaez:將一部分壓縮數據提取到內存中可能很有用,這是一個可以隨後處理的未壓縮的流。例如,SAX解析器可以在壓縮的XML文件上運行,其中部分文件被提取,解析並丟棄或進一步處理。 – 2012-02-15 08:19:54

+2

@EmilioPelaez請先詢問爲什麼在你評論之前做這件事。感謝Alex Reynolds澄清它。 – andsien 2012-02-15 08:40:58

回答

2

您可以一次解壓縮一個數據緩衝區,然後通讀它,假定文件是文本,並且可以用增量方式解析它(例如,用於處理的XML數據一個SAX解析器)。

這是我寫的一個例程,它從zip-stream中提取數據,並一次打印出一行。您可以修改它來打印或解析N字符。或者你可以將行添加到行緩衝區,並且一次處理/解析一大塊行。

這使用zlib,如果這個代碼是對你有用,可隨時使用它:

# 
# compile with -lz option in order to link in the zlib library 
# 

#include <zlib.h> 

#define Z_CHUNK 2097152 

int unzipFile(const char *fName) 
{ 
    z_stream zStream; 
    char *zRemainderBuf = malloc(1); 
    unsigned char zInBuf[Z_CHUNK]; 
    unsigned char zOutBuf[Z_CHUNK]; 
    char zLineBuf[Z_CHUNK]; 
    unsigned int zHave, zBufIdx, zBufOffset, zOutBufIdx; 
    int zError; 
    FILE *inFp = fopen(fName, "rbR"); 

    if (!inFp) { fprintf(stderr, "could not open file: %s\n", fName); return EXIT_FAILURE; } 

    zStream.zalloc = Z_NULL; 
    zStream.zfree = Z_NULL; 
    zStream.opaque = Z_NULL; 
    zStream.avail_in = 0; 
    zStream.next_in = Z_NULL; 

    zError = inflateInit2(&zStream, (15+32)); /* cf. http://www.zlib.net/manual.html */ 
    if (zError != Z_OK) { fprintf(stderr, "could not initialize z-stream\n"); return EXIT_FAILURE; } 

    *zRemainderBuf = '\0'; 
    do { 
     zStream.avail_in = fread(zInBuf, 1, Z_CHUNK, inFp); 
     if (zStream.avail_in == 0) 
      break; 
     zStream.next_in = zInBuf; 
     do { 
      zStream.avail_out = Z_CHUNK; 
      zStream.next_out = zOutBuf; 
      zError = inflate(&zStream, Z_NO_FLUSH); 
      switch (zError) { 
       case Z_NEED_DICT: { fprintf(stderr, "Z-stream needs dictionary!\n"); return EXIT_FAILURE; } 
       case Z_DATA_ERROR: { fprintf(stderr, "Z-stream suffered data error!\n"); return EXIT_FAILURE; } 
       case Z_MEM_ERROR: { fprintf(stderr, "Z-stream suffered memory error!\n"); return EXIT_FAILURE; } 
      } 
      zHave = Z_CHUNK - zStream.avail_out; 
      zOutBuf[zHave] = '\0'; 

      /* copy remainder buffer onto line buffer, if not NULL */ 
      if (zRemainderBuf) { 
       strncpy(zLineBuf, zRemainderBuf, strlen(zRemainderBuf)); 
       zBufOffset = strlen(zRemainderBuf); 
      } 
      else 
       zBufOffset = 0; 

      /* read through zOutBuf for newlines */ 
      for (zBufIdx = zBufOffset, zOutBufIdx = 0; zOutBufIdx < zHave; zBufIdx++, zOutBufIdx++) { 
       zLineBuf[zBufIdx] = zOutBuf[zOutBufIdx]; 
       if (zLineBuf[zBufIdx] == '\n') { 
        zLineBuf[zBufIdx] = '\0'; 
        zBufIdx = -1; 
        fprintf(stdout, "%s\n", zLineBuf); 
       } 
      } 

      /* copy some of line buffer onto the remainder buffer, if there are remnants from the z-stream */ 
      if (strlen(zLineBuf) > 0) { 
       if (strlen(zLineBuf) > strlen(zRemainderBuf)) { 
        /* to minimize the chance of doing another (expensive) malloc, we double the length of zRemainderBuf */ 
        free(zRemainderBuf); 
        zRemainderBuf = malloc(strlen(zLineBuf) * 2); 
       } 
       strncpy(zRemainderBuf, zLineBuf, zBufIdx); 
       zRemainderBuf[zBufIdx] = '\0'; 
      } 
     } while (zStream.avail_out == 0); 
    } while (zError != Z_STREAM_END); 

    /* close gzip stream */ 
    zError = inflateEnd(&zStream); 
    if (zError != Z_OK) { 
     fprintf(stderr, "could not close z-stream!\n"); 
     return EXIT_FAILURE; 
    } 
    if (zRemainderBuf) 
     free(zRemainderBuf); 

    fclose(inFp); 

    return EXIT_SUCCESS; 
} 
+0

謝謝先生,我真的很感謝你的幫助。我會看你的代碼並研究它。 – andsien 2012-02-15 08:39:19

+0

我認爲他談論的是壓縮檔案,所以即使你的代碼會有幫助,有趣的部分將是在檔案中找到流的開始(並使用正確的算法 - 存儲,膨脹等來解壓縮它)。 – Sulthan 2013-02-14 16:51:54

+0

目前尚不清楚OP是否意味着一個「zip」文件或簡單的壓縮文件,但除了解壓zip文件成員的默認壓縮的zlib包以外,還有可用於「破解」zip文件格式的開源API。 – 2013-02-14 16:55:29

相關問題