Comment puis-je décompresser un flux gzip avec zlib?

Les fichiers au format Gzip

(créés avec le programme gzip , par exemple) utilisent l'algorithme de compression" deflate", qui est le même algorithme de compression que celui utilisé par zlib . Cependant, lorsque vous utilisez zlib pour gonfler un fichier compressé gzip, la bibliothèque renvoie un Z_DATA_ERROR .

comment utiliser zlib pour décompresser un fichier gzip?

92
demandé sur Greg Hewgill 2009-12-03 12:19:39

4 réponses

pour décompresser un fichier au format gzip avec zlib, appeler inflateInit2 avec le paramètre windowBits comme 16+MAX_WBITS , comme ceci:

inflateInit2(&stream, 16+MAX_WBITS);

si vous ne le faites pas, zlib se plaindra d'un mauvais format de flux. Par défaut, zlib crée des flux avec un en-tête zlib, et on inflate ne reconnaît pas l'en-tête gzip différent à moins que vous ne le lui demandiez. Bien que cela soit documenté à partir de la version 1.2.1 du fichier d'en-tête zlib.h , il n'est pas dans le zlib manuel . Du fichier d'en-tête:

windowBits peut aussi être supérieure à 15 pour facultatif gzip décodage. Ajouter 32 windowBits pour permettre à la zlib et gzip décodage automatique de l'en-tête détection, ou ajouter 16 pour décoder seulement le format gzip (le format zlib de retour d'un Z_DATA_ERROR ). Si un flux gzip est décodé, strm->adler est un crc32 au lieu d'une adler32.

101
répondu Greg Hewgill 2009-12-03 09:20:26

python

zlib soutien de bibliothèque :

module python zlib pour appuyer ces ainsi.

choosing windowBits

mais zlib peut décompresser tous ces formats:

  • pour la (dé-)compresser deflate format, l'utilisation de wbits = -zlib.MAX_WBITS
  • pour la (dé-)compresser zlib format, l'utilisation de wbits = zlib.MAX_WBITS
  • pour la (dé-)compresser gzip format, l'utilisation de wbits = zlib.MAX_WBITS | 16

voir documentation en http://www.zlib.net/manual.html#Advanced (section inflateInit2 )

exemples

données d'essai:

>>> 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()
>>> 

essai évident pour zlib :

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

test pour 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'

test pour 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'

les données sont également compatibles avec gzip module:

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

détection automatique d'en-tête (zlib ou gzip)

l'ajout de 32 à windowBits déclenchera la détection d'en-tête

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

utilisant gzip à la place

pour gzip données avec en-tête gzip, vous pouvez utiliser gzip module directement; mais s'il vous plaît se rappeler que sous le capot , gzip utilise zlib .

fh = gzip.open('abc.gz', 'rb')
cdata = fh.read()
fh.close()
76
répondu dnozay 2014-03-26 22:45:40

la structure de zlib et gzip est différente. zlib utilise RFC 1950 et gzip utilise RFC 1952 , ainsi ont différents en-têtes, mais le reste ont la même structure et suit le RFC 1951 .

2
répondu josep fon 2014-03-26 22:43:58

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 };

vous installez zlib en utilisant des fils

yarn add zlib
0
répondu itz-azhar 2018-02-28 12:34:31