如何膨胀部分zlib文件
我有一个用zlib的deflate()函数压缩的文件的第一个连续的2 / 3rds。 最后1/3在传输中丢失了。 原始未压缩文件为600KB。
发送器多次调用Deflate,同时将原始文件切割为2KB的块大小,并在传递Z_FINISH时将Z_NO_FLUSH传递给文件末尾。 生成的完整压缩文件已传输,但如所述部分丢失。
是否有可能恢复原始文件的一部分? 如果是的话,有什么建议吗?
我正在使用ZLIB的普通C实现和/或ZLIB的Python 2.7实现。
虽然我不懂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文件中提取所有可用的内容。
更新:正如@Mark Adler指出的那样 ; 部分内容可以使用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 "", line 1, in 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 "", line 1, in error: Error -5 while decompressing data: incomplete or truncated stream
以下似乎在理论上是可行的,但需要修改低级zlib例程才能工作。 在http://www.zlib.net/zlib_how.html中,我们找到了一个示例程序zpipe.c
,并在其逐行描述中:
CHUNK只是用于向zlib例程提供数据和从zlib例程中提取数据的缓冲区大小。 较大的缓冲区大小会更有效,尤其是对于inflate()。 如果内存可用,则应使用大约128K或256K字节的缓冲区大小。
#define CHUNK 16384 ...
这是我的建议:您将缓冲区设置得非常小 – 如果支持,甚至可以设置为单个字节。 这样,您将尽可能地解压缩到不可避免的Z_BUF_ERROR
。 此时,人们通常会丢弃收集到的数据(寻找过早的deflate_end
调用,在你的背后“清理”)但在你的情况下你可以简单地流式传输到一个文件并在你发现无法继续时关闭它。
如果错误的“最终”符号被解码,或者zlib可能过早中止,而不是输出部分符号,则输出的最后几个字节可能包含thrash。 但是你知道你的数据无论如何都不完整,所以这应该不是问题。