首页 文章

如何用zlib解压缩gzip流?

提问于
浏览
94

Gzip格式文件(例如,使用 gzip 程序创建)使用"deflate"压缩算法,该算法与zlib使用的压缩算法相同 . 但是,当使用zlib来扩展gzip压缩文件时,库会返回 Z_DATA_ERROR .

如何使用zlib解压缩gzip文件?

4 回答

  • 77

    要使用zlib解压缩gzip格式文件,请使用 windowBits 参数调用 inflateInit2 作为 16+MAX_WBITS ,如下所示:

    inflateInit2(&stream, 16+MAX_WBITS);
    

    如果你不这样做,zlib会抱怨一个糟糕的流格式 . 默认情况下,zlib使用zlib标头创建流,并且在inflate中无法识别不同的gzip标头,除非您这样说 . 虽然从 zlib.h 头文件的1.2.1版开始记录了这一点,但它不在zlib manual中 . 从头文件:

    对于可选的gzip解码,windowBits也可以大于15 . 向windowBits添加32以使用自动标头检测启用zlib和gzip解码,或添加16以仅解码gzip格式(zlib格式将返回Z_DATA_ERROR) . 如果正在解码gzip流,则strm-> adler是crc32而不是adler32 .

  • 2

    python

    zlib library supports

    python zlib 模块也将支持这些 .

    选择windowBits

    zlib 可以解压缩所有这些格式:

    • 到(de-)压缩 deflate 格式,使用 wbits = -zlib.MAX_WBITS

    • 到(de-)压缩 zlib 格式,使用 wbits = zlib.MAX_WBITS

    • 到(de-)压缩 gzip 格式,使用 wbits = zlib.MAX_WBITS | 16

    请参阅http://www.zlib.net/manual.html#Advanced中的文档(第 inflateInit2 节)

    例子

    测试数据:

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

    zlib 的明显测试:

    >>> zlib.decompress(zlib_data)
    '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'
    

    测试 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'
    

    该数据还与 gzip 模块兼容:

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

    自动标头检测(zlib或gzip)

    32 添加到 windowBits 将触发标头检测

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

    使用gzip代替

    对于带有gzip标头的 gzip 数据,您可以直接使用 gzip 模块;但please remember that under the hoodgzip 使用 zlib .

    fh = gzip.open('abc.gz', 'rb')
    cdata = fh.read()
    fh.close()
    
  • 0

    zlib和gzip的结构不同 . zlib使用RFC 1950,gzip使用RFC 1952,因此具有不同的 Headers ,但其余的具有相同的结构并遵循RFC 1951 .

  • 103

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

    您使用纱线安装 zlib

    yarn add zlib
    

相关问题