¿Cómo puedo descomprimir un flujo de gzip con zlib?
Pregunta
Los archivos de formato gzip (creados con el programa gzip
, por ejemplo) utilizan el algoritmo de compresión "desinflar", que es el mismo algoritmo de compresión como lo zlib utiliza. Sin embargo, cuando se utiliza zlib para inflar un archivo comprimido con gzip, la biblioteca devuelve un Z_DATA_ERROR
.
¿Cómo puedo usar zlib para descomprimir un archivo gzip?
Solución
Para descomprimir un archivo en formato gzip con zlib, llame inflateInit2
con el parámetro windowBits
como 16+MAX_WBITS
, como esto:
inflateInit2(&stream, 16+MAX_WBITS);
Si no lo hace, zlib se quejan acerca de un formato de flujo de mal. Por defecto, zlib crea arroyos con una cabecera zlib, y el inflado no reconoce la cabecera diferente gzip menos que le diga que así sea. Aunque esto está documentado a partir de la versión 1.2.1 del archivo de cabecera zlib.h
, que no está en el manual de href="http://www.zlib.net/manual.html#inflateInit2" rel="noreferrer"> zlib . Desde el archivo de cabecera:
windowBits
también puede ser mayor que 15 para la decodificación gzip opcional. Añadir 32 awindowBits
para permitir zlib y gzip se decodifica con automática del cabezal detección, o añadir 16 para decodificar sólo el formato gzip (formato zlib se devolver unZ_DATA_ERROR
). Si se está decodificando una corriente gzip, esstrm->adler
un crc32 en lugar de un Adler32.
Otros consejos
pitón
biblioteca- RFC 1950 (formato comprimido
zlib
) - RFC 1951 (formato comprimido
deflate
) - RFC 1952 (formato comprimido
gzip
)
El módulo de Python zlib
apoyará estos también.
windowBits eligen
Pero zlib
puede descomprimir todos esos formatos:
- a (des) comprimir formato
deflate
, el usowbits = -zlib.MAX_WBITS
- a (des) comprimir formato
zlib
, el usowbits = zlib.MAX_WBITS
- a (des) comprimir formato
gzip
, el usowbits = zlib.MAX_WBITS | 16
Consulte la documentación de http://www.zlib.net/manual.html#Advanced (sección inflateInit2
)
ejemplos
datos de prueba:
>>> 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()
>>>
prueba evidente de zlib
:
>>> zlib.decompress(zlib_data)
'test'
prueba para 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'
prueba para 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'
Los datos también es compatible con el módulo gzip
:
>>> import gzip
>>> import StringIO
>>> fio = StringIO.StringIO(gzip_data)
>>> f = gzip.GzipFile(fileobj=fio)
>>> f.read()
'test'
>>> f.close()
detección automática del cabezal (zlib o gzip)
añadiendo 32
a windowBits
desencadenará detección de cabecera
>>> zlib.decompress(gzip_data, zlib.MAX_WBITS|32)
'test'
>>> zlib.decompress(zlib_data, zlib.MAX_WBITS|32)
'test'
usando gzip
lugar
Para los datos de cabecera gzip
con gzip se puede utilizar el módulo gzip
directamente; pero Por favor recuerde que bajo el capó , gzip
utiliza 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 };
Se instala zlib
usando hilo
yarn add zlib