我有一个用zlib的deflate()函数压缩的文件的第一个连续的2 / 3rds。最后1/3在传输中丢失了。原始的未压缩文件为600KB。
变送器多次调用Deflate,同时将原始文件切割为2KB的块大小,并在传递Z_FINISH时将Z_NO_FLUSH传递到文件末尾。生成的完整压缩文件已传输,但部分丢失,如上所述。
是否可以恢复部分原始文件?如果是的话,有关于如何的任何建议?
我正在使用ZLIB的普通C实现和/或ZLIB的Python 2.7实现。
答案 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。但是你知道你的数据无论如何都是不完整的,所以这应该不是问题。