How can I decompress a gzip stream with zlib?

Gzip format files (created with the gzip program, for example) use the "deflate" compression algorithm, which is the same compression algorithm as what zlib uses. However, when using zlib to inflate a gzip compressed file, the library returns a Z_DATA_ERROR.

How can I use zlib to decompress a gzip file?

107896 次浏览

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

inflateInit2(&stream, 16+MAX_WBITS);

如果不这样做,zlib 会抱怨流格式不好。默认情况下,zlib 创建带有 zlib 头的流,而在充气状态下,除非您告诉它不同的 gzip 头,否则它不会识别出来。虽然从 zlib.h头文件的版本1.2.1开始就记录了这一点,但是它不在 zlib manual中。来自头文件:

对于可选的 gzip 解码,windowBits也可以大于15 32到 windowBits,以启用自动头部的 zlib 和 gzip 解码 detection, or add 16 to decode only the gzip format (the zlib format will 如果正在解码 gzip 流,则 strm->adler为 用 Crc32代替 Adler32。

Zlib 和 gzip 的结构不同。 zlib 使用 RFC 1950,gzip 使用 RFC 1952, so have different headers but the rest have the same structure and follows the RFC 1951.

python

zlib library supports:

Pythonzlib模块也将支持这些功能。

选择 windows 位

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

  • 要(反)压缩 deflate格式,请使用 wbits = -zlib.MAX_WBITS
  • 要(反)压缩 zlib格式,请使用 wbits = zlib.MAX_WBITS
  • 要(反)压缩 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()
>>>

obvious test for zlib:

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

test for 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模块; 但是 请记住,在引擎盖下gzip使用 zlib

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