zlib错误:解压缩时错误 -3:头部检查不正确

76 投票
9 回答
128097 浏览
提问于 2025-04-16 00:27

我有一个gzip格式的文件,我想用Python来读取它,代码如下:

import zlib

do = zlib.decompressobj(16+zlib.MAX_WBITS)
fh = open('abc.gz', 'rb')
cdata = fh.read()
fh.close()
data = do.decompress(cdata)

但是它报了这个错:

zlib.error: Error -3 while decompressing: incorrect header check

我该怎么解决这个问题呢?

9 个回答

3

我刚刚解决了在解压缩gzipped数据时遇到的“错误的头检查”问题。

你需要在调用inflateInit2时设置-WindowsBits => WANT_GZIP(使用2版本)。

是的,这确实让人很沮丧。通常,简单浏览文档会让人觉得Zlib是用来进行Gzip压缩的接口,但默认情况下(不使用gz*的方法),它并不会创建或解压Gzip格式。你必须发送这个不太显眼的标志。

160

你遇到了这个错误:

zlib.error: Error -3 while decompressing: incorrect header check

这很可能是因为你在检查一些不存在的头信息,比如你的数据是按照 RFC 1951deflate 压缩格式)来处理的,而不是 RFC 1950zlib 压缩格式)或 RFC 1952gzip 压缩格式)。

选择 windowBits

不过,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()
>>> 

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)  # io.BytesIO for Python 3
>>> f = gzip.GzipFile(fileobj=fio)
>>> f.read()
'test'
>>> f.close()

自动头信息检测(zlib 或 gzip)

windowBits 中加上 32 会触发头信息检测。

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

直接使用 gzip

或者你可以忽略 zlib,直接使用 gzip 模块;但 请记住,实际上gzip 是在使用 zlib

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

更新: dnozay的回答解释了这个问题,并且应该被认为是正确的答案。


可以试试 gzip 模块,下面的代码直接来自于 Python文档

import gzip
f = gzip.open('/home/joe/file.txt.gz', 'rb')
file_content = f.read()
f.close()

撰写回答