如何膨胀部分zlib文件

时间:2013-12-16 20:35:46

标签: python c zlib compression

我有一个用zlib的deflate()函数压缩的文件的第一个连续的2 / 3rds。最后1/3在传输中丢失了。原始的未压缩文件为600KB。

变送器多次调用Deflate,同时将原始文件切割为2KB的块大小,并在传递Z_FINISH时将Z_NO_FLUSH传递到文件末尾。生成的完整压缩文件已传输,但部分丢失,如上所述。

是否可以恢复部分原始文件?如果是的话,有关于如何的任何建议?

我正在使用ZLIB的普通C实现和/或ZLIB的Python 2.7实现。

3 个答案:

答案 0 :(得分:14)

虽然我不懂python,但我设法让它工作:

#!/usr/bin/python
import sys
import zlib
f = open(sys.argv[1], "rb")
g = open(sys.argv[2], "wb")
z = zlib.decompressobj()
while True:
    buf = z.unconsumed_tail
    if buf == "":
        buf = f.read(8192)
        if buf == "":
            break
    got = z.decompress(buf)
    if got == "":
        break
    g.write(got)

这应该从部分zlib文件中提取所有可用的内容。

答案 1 :(得分:2)

更新:作为@Mark Adler pointed out;部分内容可以使用zlib.decompressobj解压缩:

>>> decompressor = zlib.decompressobj()
>>> decompressor.decompress(part)
"let's compress some t"

其中part定义如下。

---旧评论如下:

默认情况下,zlib不处理Python中的部分内容。

这有效:

>>> compressed = "let's compress some text".encode('zip')
>>> compressed
'x\x9c\xcbI-Q/VH\xce\xcf-(J-.V(\xce\xcfMU(I\xad(\x01\x00pX\t%'
>>> compressed.decode('zip')
"let's compress some text"

如果我们截断它,它就不起作用了:

>>> part = compressed[:3*len(compressed)/4]
>>> part.decode('zip')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File ".../lib/python2.7/encodings/zlib_codec.py", lin
e 43, in zlib_decode
    output = zlib.decompress(input)
error: Error -5 while decompressing data: incomplete or truncated stream

如果我们明确使用zlib,则相同:

>>> import zlib
>>> zlib.decompress(compressed)
"let's compress some text"
>>> zlib.decompress(part)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
error: Error -5 while decompressing data: incomplete or truncated stream

答案 2 :(得分:0)

以下似乎在理论上是可行的,但需要修改低级zlib例程才能工作。在http://www.zlib.net/zlib_how.html中,我们找到了一个示例程序zpipe.c,并逐行描述:

  

CHUNK只是用于向zlib例程提供数据和从中提取数据的缓冲区大小。较大的缓冲区大小会更有效,尤其是对于inflate()。如果内存可用,则应使用大小为128K或256K字节的缓冲区大小。

#define CHUNK 16384
...

这是我的建议:您将缓冲区设置得非常小 - 如果支持,甚至可以设置为单个字节。这样,您将尽可能地解压缩到不可避免的Z_BUF_ERROR。此时,通常会丢弃收集的数据(查找在您背后“清理”的过早deflate_end次调用)但在您的情况下,您可以简单地流式传输到文件并在发现无法关闭时关闭它继续。

如果错误的“最终”符号被解码,或者zlib可能过早中止,而不是输出部分符号,则输出的最后几个字节可能包含thrash。但是你知道你的数据无论如何都是不完整的,所以这应该不是问题。