¿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?

Author: Greg Hewgill, 2009-12-03

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 a windowBits 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 un Z_DATA_ERROR). Si se está decodificando un flujo gzip, strm->adler es un crc32 en lugar de un adler32.

 101
Author: Greg Hewgill,
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

zlib la biblioteca soporta :

El módulo python zlib también los soportará.

Elegir ventanas

Pero zlib puede descomprimir todos esos formatos:

  • para (des-)comprimir el formato deflate, use wbits = -zlib.MAX_WBITS
  • a (de-)comprimir zlib formato, utilizar wbits = zlib.MAX_WBITS
  • para (des-)comprimir el formato gzip, use wbits = 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()
 76
Author: dnozay,
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.

 2
Author: josep fon,
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
 0
Author: itz-azhar,
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