¿Cómo puedo descomprimir un flujo gzip con zlib?
Los archivos de formato Gzip (creados con el programa gzip
, por ejemplo) usan el algoritmo de compresión "deflate", que es el mismo algoritmo de compresión que usa zlib. Sin embargo, cuando se utiliza zlib para inflar un archivo comprimido gzip, la biblioteca devuelve un Z_DATA_ERROR
.
¿Cómo puedo usar zlib para descomprimir un archivo gzip?
4 answers
Para descomprimir un archivo de formato gzip con zlib, llame a inflateInit2
con el parámetro windowBits
como 16+MAX_WBITS
, así:
inflateInit2(&stream, 16+MAX_WBITS);
Si no haces esto, zlib se quejará de un mal formato de flujo. De forma predeterminada, zlib crea flujos con un encabezado zlib, y al inflar no reconoce el encabezado gzip diferente a menos que se lo indique. Aunque esto está documentado a partir de la versión 1.2.1 del archivo de cabecera zlib.h
, no está en el manual 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 habilitar la decodificación zlib y gzip con encabezado automático detección, o agregue 16 para decodificar solo el formato gzip (el formato zlib devuelve unZ_DATA_ERROR
). Si se está decodificando un flujo gzip,strm->adler
es un crc32 en lugar de un adler32.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-03 09:20:26
Python
-
RFC 1950 (
zlib
formato comprimido) -
RFC 1951 (
deflate
formato comprimido) -
RFC 1952 (
gzip
formato comprimido)
El módulo python zlib
también los soportará.
Elegir ventanas
Pero zlib
puede descomprimir todos esos formatos:
- para (des-)comprimir el formato
deflate
, usewbits = -zlib.MAX_WBITS
- a (de-)comprimir
zlib
formato, utilizarwbits = zlib.MAX_WBITS
- para (des-)comprimir el formato
gzip
, usewbits = zlib.MAX_WBITS | 16
Véase la documentación en 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 obvia para 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 son compatibles 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 de cabecera (zlib o gzip)
Agregar 32
a windowBits
activará la detección de encabezado
>>> zlib.decompress(gzip_data, zlib.MAX_WBITS|32)
'test'
>>> zlib.decompress(zlib_data, zlib.MAX_WBITS|32)
'test'
Usando gzip
en su lugar
Para gzip
datos con encabezado gzip puede usar el módulo gzip
directamente; pero recuerde que debajo del capó, gzip
usa zlib
.
fh = gzip.open('abc.gz', 'rb')
cdata = fh.read()
fh.close()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-26 22:45:40
La estructura de zlib y gzip es diferente. zlib utiliza RFC 1950 y gzip utiliza RFC 1952 , así que tienen diferentes encabezados, pero el resto tienen la misma estructura y sigue el RFC 1951.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-26 22:43:58
Nodo.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 yarn
yarn add zlib
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-28 12:34:31