2010-03-11 75 views
30

我有一个内存和磁盘有限的环境,我需要解压发送给我的基于字符串的块(通过xmlrpc二进制传输)的gzip文件的内容。但是,使用zlib.decompress()或zlib.decompressobj()/解压缩()barf通过gzip头。我已经尝试通过gzip头部进行抵消(记录在here),但仍然没有设法避开barf。 gzip库本身似乎只支持从文件解压缩。Python解压gzip块逐块

下面的代码片段给出了我想做些什么的简化图(除了在现实生活中的缓冲区将从XMLRPC填补,而不是从本地文件读取):

#! /usr/bin/env python 

import zlib 

CHUNKSIZE=1000 

d = zlib.decompressobj() 

f=open('23046-8.txt.gz','rb') 
buffer=f.read(CHUNKSIZE) 

while buffer: 
    outstr = d.decompress(buffer) 
    print(outstr) 
    buffer=f.read(CHUNKSIZE) 

outstr = d.flush() 
print(outstr) 

f.close() 

不幸的是,我说,这barfs有:

Traceback (most recent call last): 
    File "./test.py", line 13, in <module> 
    outstr = d.decompress(buffer) 
zlib.error: Error -3 while decompressing: incorrect header check 

从理论上讲,我可以养活我的XML-RPC源数据到一个StringIO的,然后使用该作为gzip.GzipFile()一FileObj文件,然而,在现实生活中,我不没有可用的内存来保存整个文件内容以及t他解压缩数据。我真的需要逐块处理它。

回退可能会将我的xmlrpc源数据的压缩从gzip更改为纯zlib,但由于这会影响其他子系统,所以如果可能,我宁愿避免它。

任何想法?

回答

38

gzip和zlib使用稍微不同的标题。

How can I decompress a gzip stream with zlib?

尝试d = zlib.decompressobj(16+zlib.MAX_WBITS)

出于可能的性能原因,您可能会尝试将块大小更改为2(例如CHUNKSIZE=1024)的幂。

+0

这样做完美。谢谢。 (现在,为什么python文档中没有提示?) – user291294 2010-03-11 14:30:23

+4

zlib只是z版本的zlib的一个包装。它没有很好的记录。请注意,16 + zlib.MAX_WBITS也没有记录在c版本中,并且这不是我第一次见到未公开的zlib功能。 – wisty 2010-03-12 17:33:56

+0

肯定需要记录! – Ross 2011-10-17 03:48:23