2012-01-07 147 views
2

我有一個內存中的gzip文件,我想使用zlib 1.1.3版解壓縮它。 Uncompress()返回-3,Z_DATA_ERROR,表示源數據已損壞。使用zlib版本1.1.3解壓縮內存中的gzip文件

我知道我的內存緩衝區是正確的 - 如果我將緩衝區寫入文件,它與我的源gzip文件相同。

The gzip file format表示有一個10字節的標題,可選的標題,數據和頁腳。是否有可能確定數據的起始位置,並將該部分去掉?我對這個主題進行了搜索,幾個人建議使用inflateInit2()。但是,在我的zlib版本中,該函數被奇怪地註釋掉了。還有其他的選擇嗎?

+4

你有什麼特別的理由想要使用1.1.3版本嗎?版本1.1.4於2002年3月發佈,最新版本爲1.2.5。 – ruakh 2012-01-07 03:04:28

+0

我知道我使用的版本比較陳舊,但這是一個不允許更新zlib的傳統項目。 – gmletzkojr 2012-01-07 13:33:00

回答

0

是否可以確定數據的起始位置,並將該部分去掉?

Gzip已具有以下magic number

static const unsigned char gzipMagicBytes[] = { 0x1f, 0x8b, 0x08, 0x00 }; 

您可以通過文件流中讀取並查找這些字節:

static const int testElemSize = sizeof(unsigned char); 
static const int testElemCount = sizeof(gzipMagicBytes); 

const char *fn = "foo.bar"; 
FILE *fp = fopen(fn, "rbR"); 
char testMagicBuffer[testElemCount] = {0}; 
unsigned long long testMagicOffset = 0ULL; 

if (fp != NULL) { 
    do { 
     if (memcmp(testMagicBuffer, gzipMagicBytes, sizeof(gzipMagicBytes)) == 0) { 
      /* we found gzip magic bytes, do stuff here... */ 
      fprintf(stdout, "gzip stream found at byte offset: %llu\n", testMagicOffset); 
      break; 
     } 
     testMagicOffset += testElemSize * testElemCount; 
     fseek(fp, testMagicOffset - testElemCount + 1, SEEK_SET); 
     testMagicOffset -= testElemCount + 1; 
    } while (fread(testMagicBuffer, testElemSize, testElemCount, fp)); 
} 

fclose(fp); 

一旦失調,你可以做複製和粘貼操作或覆蓋其他字節等。

1

我遇到了同樣的問題,其他zlib版本(1.2.7)
我不知道爲什麼inflateInit2()被註釋掉了。

如果不調用inflateInit2你可以做到以下幾點:

err = inflateInit(&d_stream); 
err = inflateReset2(&d_stream, 31); 

的inflateReset2也被稱爲inflateInit。在inflateInit中,WindowBits被設置爲15(1111二進制)。但你必須將它們設置爲31(11111)才能使用gzip。

其原因是在這裏:

內部inflateReset2以下完成:

wrap = (windowBits >> 4) + 1; 

如果窗口位被置15(1111二進制)和2,如果窗口位被設置,這導致1 31(11111)

現在如果調用充氣()在HEAD狀態以下行與幻數gzip的

if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ 
01沿着檢查狀態 - >包裹值

所以用下面的代碼,我能夠做內存的gzip壓縮: (注:此代碼假定進行解壓縮完整的數據在內存中,並且爲解壓縮數據緩衝區足夠大)

int err; 
z_stream d_stream; // decompression stream 



d_stream.zalloc = (alloc_func)0; 
d_stream.zfree = (free_func)0; 
d_stream.opaque = (voidpf)0; 

d_stream.next_in = deflated; // where deflated is a pointer the the compressed data buffer 
d_stream.avail_in = deflatedLen; // where deflatedLen is the length of the compressed data 
d_stream.next_out = inflated; // where inflated is a pointer to the resulting uncompressed data buffer 
d_stream.avail_out = inflatedLen; // where inflatedLen is the size of the uncompressed data buffer 

err = inflateInit(&d_stream); 
err = inflateReset2(&d_stream, 31); 
err = inflateEnd(&d_stream); 

只需在inflateInit2()中進行註釋即可獲得解決方案。在這裏你可以直接設置WindowBits