Come posso decomprimere un flusso di gzip con zlib?
Domanda
file formato gzip (creati con il programma gzip
, per esempio) utilizzano l'algoritmo di compressione "sgonfia", che è lo stesso algoritmo di compressione come quello che zlib utilizza. Tuttavia, quando si utilizza zlib per gonfiare un file compresso con gzip, la biblioteca restituisce un Z_DATA_ERROR
.
Come posso utilizzare zlib per decomprimere un file gzip?
Soluzione
Per decomprimere un file in formato gzip con zlib, chiamare inflateInit2
con il parametro windowBits
come 16+MAX_WBITS
, in questo modo:
inflateInit2(&stream, 16+MAX_WBITS);
Se non si esegue questa operazione, zlib si lamenta perché un formato di flusso male. Per impostazione predefinita, zlib crea flussi di testa zlib, e gonfiare non riconosce la diversa intestazione gzip a meno che non gli si dice così. Anche se questo è documentato a partire dalla versione 1.2.1 del file di intestazione zlib.h
, non è nel zlib . Dal file di intestazione:
windowBits
può anche essere maggiore di 15 per la decodifica gzip opzionale. Inserisci 32 awindowBits
per consentire zlib e gzip decodifica con intestazione automatica rilevamento, o aggiungere 16 per decodificare solo il formato gzip (il formato sarà zlib restituire unZ_DATA_ERROR
). Se un flusso gzip viene decodificato,strm->adler
è un CRC32 invece di un Adler32.
Altri suggerimenti
python
- RFC 1950 (formato compresso
zlib
) - RFC 1951 (formato compresso
deflate
) - RFC 1952 (formato compresso
gzip
)
Il modulo python zlib
sosterrà questi pure.
windowBits scegliendo
Ma zlib
può decomprimere tutti questi formati:
- (dis) comprimere formato
deflate
, usowbits = -zlib.MAX_WBITS
- (dis) comprimere formato
zlib
, usowbits = zlib.MAX_WBITS
- (dis) comprimere formato
gzip
, usowbits = zlib.MAX_WBITS | 16
Si veda 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()
>>>
prova evidente 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 è inoltre compatibile con il modulo gzip
:
>>> import gzip
>>> import StringIO
>>> fio = StringIO.StringIO(gzip_data)
>>> f = gzip.GzipFile(fileobj=fio)
>>> f.read()
'test'
>>> f.close()
rilevazione automatica di intestazione (zlib o gzip)
aggiungendo 32
a windowBits
attiverà il rilevamento di intestazione
>>> zlib.decompress(gzip_data, zlib.MAX_WBITS|32)
'test'
>>> zlib.decompress(zlib_data, zlib.MAX_WBITS|32)
'test'
utilizzando gzip
invece
Per i dati gzip
con intestazione gzip è possibile utilizzare il modulo gzip
direttamente; ma si ricorda che sotto il cofano , gzip
utilizza zlib
.
fh = gzip.open('abc.gz', 'rb')
cdata = fh.read()
fh.close()
Node.js
const { gunzip } = require('zlib');
const decompressGzip = compressedData =>
new Promise((resolve, reject) => {
gunzip(compressedData, (error, decompressedData) => {
if (error) return reject(error);
return resolve(decompressedData);
});
});
module.exports = { decompressGzip };
Si installa zlib
usando filato
yarn add zlib