所以这就是问题所在.我有sample.gz文件,大小约为60KB.我想解压缩此文件的前2000个字节.我正在运行CRC校验失败错误,我猜因为gzip CRC字段出现在文件的末尾,它需要整个gzip文件进行解压缩.有办法解决这个问题吗?我不关心CRC检查.即使我因CRC错误而无法解压缩,也没关系.有没有办法绕过这个并解压缩部分.gz文件?
我到目前为止的代码是
import gzip
import time
import StringIO
file = open('sample.gz', 'rb')
mybuf = MyBuffer(file)
mybuf = StringIO.StringIO(file.read(2000))
f = gzip.GzipFile(fileobj=mybuf)
data = f.read()
print data
Run Code Online (Sandbox Code Playgroud)
遇到的错误是
File "gunzip.py", line 27, in ?
data = f.read()
File "/usr/local/lib/python2.4/gzip.py", line 218, in read
self._read(readsize)
File "/usr/local/lib/python2.4/gzip.py", line 273, in _read
self._read_eof()
File "/usr/local/lib/python2.4/gzip.py", line 309, in _read_eof
raise IOError, "CRC check failed"
IOError: CRC check failed
Run Code Online (Sandbox Code Playgroud)
还有什么方法可以使用zlib模块执行此操作并忽略gzip标头?
jif*_*lub 13
gzip模块的问题不在于它无法解压缩部分文件,只有在尝试验证解压缩内容的校验和时才会发生错误.(原始校验和存储在压缩文件的末尾,因此验证永远不会使用部分文件.)
关键是欺骗gzip跳过验证.caesar0301的答案是通过修改gzip源代码来实现的,但是没有必要这么做,简单的猴子修补就行了.gzip.GzipFile._read_eof
当我解压缩部分文件时,我写了这个上下文管理器暂时替换:
import contextlib
@contextlib.contextmanager
def patch_gzip_for_partial():
"""
Context manager that replaces gzip.GzipFile._read_eof with a no-op.
This is useful when decompressing partial files, something that won't
work if GzipFile does it's checksum comparison.
"""
_read_eof = gzip.GzipFile._read_eof
gzip.GzipFile._read_eof = lambda *args, **kwargs: None
yield
gzip.GzipFile._read_eof = _read_eof
Run Code Online (Sandbox Code Playgroud)
示例用法:
from cStringIO import StringIO
with patch_gzip_for_partial():
decompressed = gzip.GzipFile(StringIO(compressed)).read()
Run Code Online (Sandbox Code Playgroud)
mjv*_*mjv 12
我似乎需要查看Python zlib库
GZIP格式依赖于zlib,但引入了文件级压缩概念以及CRC校验,这似乎是您目前不想要/不需要的.
例如,请参阅Dough Hellman提供的这些代码片段
编辑:Doubh Hellman网站上的代码仅显示如何使用zlib压缩或解压缩.如上所述,GZIP是"带有包络的zlib",在获取zlib压缩数据本身之前,您需要解码envellope .这里有更多关于它的信息,它真的不那么复杂:
很抱歉既不提供简单的程序也不提供随时可用的代码段,但是使用上述指示解码文件应该相对快速和简单.
rjm*_*nro 10
我看不出你想要解压缩前2000个压缩字节的任何可能原因.根据数据,这可能会解压缩到任意数量的输出字节.
当然,您想要解压缩文件,并在您根据需要解压缩尽可能多的文件时停止,例如:
f = gzip.GzipFile(fileobj=open('postcode-code.tar.gz', 'rb'))
data = f.read(4000)
print data
Run Code Online (Sandbox Code Playgroud)
AFAIK,这不会导致整个文件被读取.它只能读取获得前4000个字节所需的数量.