Come posso decomprimere un flusso gzip con zlib?


108

I file in formato Gzip (creati con il gzipprogramma, ad esempio) utilizzano l'algoritmo di compressione "deflate", che è lo stesso algoritmo di compressione utilizzato da zlib . Tuttavia, quando si utilizza zlib per gonfiare un file compresso gzip, la libreria restituisce un file Z_DATA_ERROR.

Come posso utilizzare zlib per decomprimere un file gzip?

Risposte:


118

Per decomprimere un file in formato gzip con zlib, chiama inflateInit2con il windowBitsparametro as 16+MAX_WBITS, in questo modo:

inflateInit2(&stream, 16+MAX_WBITS);

Se non lo fai, zlib si lamenterà di un cattivo formato di flusso. Per impostazione predefinita, zlib crea flussi con un'intestazione zlib e su infllate non riconosce l'intestazione gzip diversa a meno che tu non lo dica. Sebbene questo sia documentato a partire dalla versione 1.2.1 del zlib.hfile di intestazione, non è nel manuale di zlib . Dal file di intestazione:

windowBitspuò anche essere maggiore di 15 per la decodifica gzip opzionale. Aggiungi 32 a windowBitsper abilitare la decodifica zlib e gzip con il rilevamento automatico dell'intestazione, oppure aggiungi 16 per decodificare solo il formato gzip (il formato zlib restituirà a Z_DATA_ERROR). Se un flusso gzip viene decodificato, strm->adlerè un crc32 invece di un adler32.


35
In Python:zlib.decompress(data, 15 + 32)
Roman Starkov

3
Grazie, è stato molto frustrante finché non ho trovato questo post.
Alex

Wow, questa è la domanda del 2009. Grazie @Greg Hewgill
YuAn Shaolin Maculelê Lai

Forse puoi fornire alcune linee guida per la decompressione iterativa del flusso gzip. Nella decompressione gzip one-shot in cui il flusso di output e la dimensione dovrebbero essere fissi e sufficienti per memorizzare l'intero output decompresso. Questo valore dipende dall'efficacia della decompressione gzip che può variare in base all'entropia dei dati. C'è un modo per allocare dinamicamente più spazio al buffer di output quando necessario? Grazie
Zohar81

104

pitone

zlibla libreria supporta :

Il zlibmodulo python supporterà anche questi.

scegliendo windowBits

Ma zlibpuò decomprimere tutti quei formati:

  • per (de-) comprimere il deflateformato, usawbits = -zlib.MAX_WBITS
  • per (de-) comprimere il zlibformato, usawbits = zlib.MAX_WBITS
  • per (de-) comprimere il gzipformato, usawbits = zlib.MAX_WBITS | 16

Consulta la documentazione in http://www.zlib.net/manual.html#Advanced (sezione inflateInit2)

esempi

dati di test:

>>> deflate_compress = zlib.compressobj(9, zlib.DEFLATED, -zlib.MAX_WBITS)
>>> zlib_compress = zlib.compressobj(9, zlib.DEFLATED, zlib.MAX_WBITS)
>>> gzip_compress = zlib.compressobj(9, zlib.DEFLATED, zlib.MAX_WBITS | 16)
>>> 
>>> text = '''test'''
>>> deflate_data = deflate_compress.compress(text) + deflate_compress.flush()
>>> zlib_data = zlib_compress.compress(text) + zlib_compress.flush()
>>> gzip_data = gzip_compress.compress(text) + gzip_compress.flush()
>>> 

test ovvio per zlib:

>>> zlib.decompress(zlib_data)
'test'

prova per deflate:

>>> zlib.decompress(deflate_data)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
zlib.error: Error -3 while decompressing data: incorrect header check
>>> zlib.decompress(deflate_data, -zlib.MAX_WBITS)
'test'

prova per gzip:

>>> zlib.decompress(gzip_data)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
zlib.error: Error -3 while decompressing data: incorrect header check
>>> zlib.decompress(gzip_data, zlib.MAX_WBITS|16)
'test'

i dati sono anche compatibili con il gzipmodulo:

>>> import gzip
>>> import StringIO
>>> fio = StringIO.StringIO(gzip_data)
>>> f = gzip.GzipFile(fileobj=fio)
>>> f.read()
'test'
>>> f.close()

rilevamento automatico dell'intestazione (zlib o gzip)

l'aggiunta 32a windowBitsattiverà il rilevamento dell'intestazione

>>> zlib.decompress(gzip_data, zlib.MAX_WBITS|32)
'test'
>>> zlib.decompress(zlib_data, zlib.MAX_WBITS|32)
'test'

usando gzipinvece

Per i gzipdati con intestazione gzip puoi usare gzipdirettamente il modulo; ma per favore ricorda che sotto il cofano , gzipusa zlib.

fh = gzip.open('abc.gz', 'rb')
cdata = fh.read()
fh.close()

3
perché questo pezzo d'oro non è sui documenti esattamente in questo formato?
Ramon Moraes

sentiti libero di inviare una richiesta pull / patch contro cpython usando una qualsiasi di questa risposta.
dnozay

ottima risposta per le stringhe, qualche idea su come farlo per un flusso senza leggere l'intero file in memoria?
Josh J

Grazie. Posso risolvere il mio problema di decompressione nel mio codice sorgente con la tua risposta.
Bethlee

incredibile, questa è una pepita d'oro .. tuttavia non posso fare a meno di sentire che questi sono equivalenti a "numeri magici"? dove nella documentazione è menzionato? ho guardato, ma devo aver controllato abbastanza bene .. inoltre, la notazione non la seguo completamente. Cosa fa il | significa, è facoltativo? e perché è deflate negativo .. è MAX_WBITS una costante .. 🙁
m1nkeh

3

La struttura di zlib e gzip è diversa. zlib utilizza RFC 1950 e gzip utilizza RFC 1952 , quindi hanno intestazioni diverse ma il resto ha la stessa struttura e segue l' RFC 1951 .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.