Comment puis-je décomprimer un flux gzip avec zlib?
Question
fichiers au format Gzip (créés avec le programme gzip
, par exemple) utilisent le "dégonfler" algorithme de compression, qui est le même algorithme de compression que zlib utilise. Cependant, lors de l'utilisation zlib pour gonfler un fichier compressé gzip, la bibliothèque retourne un Z_DATA_ERROR
.
Comment puis-je utiliser zlib pour décompresser un fichier gzip?
La solution
Pour décompresser un fichier au format gzip avec zlib, appelez 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 plaindre d'un mauvais format de flux. Par défaut, zlib crée des cours d'eau avec un en-tête de zlib, et gonflent ne reconnaît pas l'autre entête du fichier à moins que vous dire ainsi. Bien que cela soit documenté à partir de la version 1.2.1 du fichier d'en-tête de zlib.h
, il est dans le manuel zlib . A partir du fichier d'en-tête:
windowBits
peut aussi être supérieure à 15 pour le décodage gzip en option. Ajouter 32 àwindowBits
pour permettre zlib et gzip décodage avec tête automatique détection, ou ajouter 16 à décoder uniquement le format gzip (le format zlib sera retourner unZ_DATA_ERROR
). Si un flux gzip est décodé,strm->adler
est un crc32 au lieu d'un adler32.
Autres conseils
python
- RFC 1950 (
zlib
format compressé) - RFC 1951 (
deflate
format compressé) - RFC 1952 (
gzip
format compressé)
Le module zlib
python soutiendra ceux-ci ainsi.
choisir windowBits
Mais zlib
peut décomprimer tous ces formats:
- (dé) compression format
deflate
, utilisezwbits = -zlib.MAX_WBITS
- (dé) compression format
zlib
, utilisezwbits = zlib.MAX_WBITS
- (dé) compression format
gzip
, utilisezwbits = zlib.MAX_WBITS | 16
Voir la documentation en http://www.zlib.net/manual.html#Advanced (section inflateInit2
)
Exemples
données de 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()
>>>
Test évident pour zlib
:
>>> zlib.decompress(zlib_data)
'test'
test 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 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 est également compatible avec le module gzip
:
>>> 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)
ajouter 32
à windowBits
déclenche 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'
en utilisant à la place gzip
Pour les données de gzip
avec en-tête de gzip, vous pouvez utiliser le module de gzip
directement; mais s'il vous plaît rappelez-vous que sous le capot , gzip
utilise 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 };
Vous installez le fil à l'aide zlib
yarn add zlib