我正在编写一个脚本,它将与来自仪器的数据一起作为gzip流使用。在大约90%的情况下,gzip
模块可以很好地工作,但其中一些流会导致产生IOError: Not a gzipped file
。如果gzip标题被删除,deflate流直接送到zlib
,我改为Error -3 while decompressing data: incorrect header check
。在将我的头撞向墙壁大约半天之后,我发现有问题的流包含看似随机数量的附加字节(不是gzip数据的一部分),并附加到最后。我如何使用包含额外数据的Gzip文件?
这令我奇怪的是,Python不能使用这些文件的原因有两个:
- GZIP和7zip的能够打开这些“填充”的文件没有问题。 (Gzip已产生的消息
decompression OK, trailing garbage ignored
,7zip的成功默默) 无论是gzip和Python文档似乎表明,这应该工作:(重点煤矿)
必须能够到 无论压缩数据的实际大小如何,都可以使用任何压缩方法检测压缩数据的结尾,即 。 特别地, 解压缩器必须能够面向记录的文件系统上的检测和跳过所附 额外的数据为有效的压缩文件,或者当 的压缩数据只能从一个装置在一个 的倍数读一定的块大小。
调用
GzipFile
对象的close()
方法不会关闭FileObj文件,,因为你可能希望压缩数据后追加更多的材料。这也可以让您将打开写作StringIO
对象FileObj文件和检索使用StringIO
对象的getvalue()
方法所产生的内存缓冲区。Python's
zlib.Decompress.unused_data
:包含过去压缩的数据的末尾的字节的任何一个字符串。也就是说,这将保持
""
,直到包含压缩数据的最后一个字节可用。 如果整个串变成了包含压缩数据,这是""
,空字符串。的唯一方式来确定压缩数据的字符串结尾是通过实际解压缩它。这意味着,当压缩数据包含在一个较大的文件的一部分,你只能通过读取数据发现它的结束和喂养它其次是一些非空字符串为减压对象的
decompress()
方法,直到unused_data
属性不再空的字符串。
这里是我试过的四种方法。 (这些例子是Python 3.1,但我测试过2.5和2.7,并且有同样的问题。)
# approach 1 - gzip.open
with gzip.open(filename) as datafile:
data = datafile.read()
# approach 2 - gzip.GzipFile
with open(filename, "rb") as gzipfile:
with gzip.GzipFile(fileobj=gzipfile) as datafile:
data = datafile.read()
# approach 3 - zlib.decompress
with open(filename, "rb") as gzipfile:
data = zlib.decompress(gzipfile.read()[10:])
# approach 4 - zlib.decompressobj
with open(filename, "rb") as gzipfile:
decompressor = zlib.decompressobj()
data = decompressor.decompress(gzipfile.read()[10:])
我做错了什么?
UPDATE
好,同时与gzip
的问题似乎是在模块中的一个错误,我zlib
问题是自己造成的。 ;-)
在挖掘到gzip.py
时我意识到我在做什么错了 - 默认情况下,zlib.decompress
等。期望zlib-wrapped流,而不是裸露的缩小流。通过传入负值wbits
,您可以告知zlib
跳过zlib标题并对原始流进行解压缩。这两个工作:
# approach 5 - zlib.decompress with negative wbits
with open(filename, "rb") as gzipfile:
data = zlib.decompress(gzipfile.read()[10:], -zlib.MAX_WBITS)
# approach 6 - zlib.decompressobj with negative wbits
with open(filename, "rb") as gzipfile:
decompressor = zlib.decompressobj(-zlib.MAX_WBITS)
data = decompressor.decompress(gzipfile.read()[10:])
其实我搞乱大约有`gzip`的内部位在调试的问题,但它没有发生,我来解决那里的问题并用我的脚本打包修改后的模块。这真是丑陋,但听起来它可能仍然是最好的选择。 : -/ – 2011-02-08 01:29:56
@Ben:它是独立的,至少它不是一项重大成本;只有一个文件。本地模块更令人讨厌。 – 2011-02-08 01:34:11