在python zlib的减压(zlib decompression in python)

2019-08-02 03:51发布

好了,所以我有python的(2.6)zlib.compress()函数压缩一些数据流。 当我尝试解压缩,其中一些将无法解压缩(zlib的错误-5,这似乎是一个“缓冲区错误”,不知道做的什么)。 起初,我以为我是这样做,但我意识到,我都无法解压缩开始0x78DA(工作的人是0x789C),和我环顾四周,这似乎是一种不同的zlib压缩的那些 - 中神奇的数字变化取决于使用的压缩。 我可以用它来解压缩文件? 我在大清洗?

Answer 1:

根据RFC 1950年 ,“确定” 0x789C和“坏” 0x78DA之间的区别是在FLEVEL位字段:

  FLEVEL (Compression level)
     These flags are available for use by specific compression
     methods.  The "deflate" method (CM = 8) sets these flags as
     follows:

        0 - compressor used fastest algorithm
        1 - compressor used fast algorithm
        2 - compressor used default algorithm
        3 - compressor used maximum compression, slowest algorithm

     The information in FLEVEL is not needed for decompression; it
     is there to indicate if recompression might be worthwhile.

“OK”使用2,“坏”的使用3.因此,在本身的区别是没有问题的。

为了进一步得到任何,你可能会考虑提供每个压缩和(未遂)的以下信息解压缩:什么平台,Python的是什么版本,zlib库,究竟是什么用来调用zlib的模块的实际代码是什么版本。 还提供从故障减压尝试全面追踪和错误消息。 您是否尝试过失败的文件与任何其他zlib的阅读软件解压缩? 结果又如何? 请说明你有什么一起工作:请问“我是大清洗?” 意味着你没有访问原始数据? 它怎么从流文件中得到什么? 你有什么保证数据不传输错位?

更新基于刊登在你的自我的答案部分澄清一些意见:

您正在使用Windows。 二进制模式,在读取时文本模式和写入文件之间的区别的Windows。 当在文本模式下阅读,Python的2.x的变化 '\ r \ n' 到 '\ n',并改变 '\ n' 到 '\ r \ n' 写入时。 与非文本数据时,这是不是一个好主意。 更糟的是,在文本模式下阅读时,“\ X1A”又名按Ctrl-Z被视为档案结尾。

要压缩文件:

# imports and other superstructure left as a exercise
str_object1 = open('my_log_file', 'rb').read()
str_object2 = zlib.compress(str_object1, 9)
f = open('compressed_file', 'wb')
f.write(str_object2)
f.close()

要解压缩文件:

str_object1 = open('compressed_file', 'rb').read()
str_object2 = zlib.decompress(str_object1)
f = open('my_recovered_log_file', 'wb')
f.write(str_object2)
f.close()

旁白:最好使用gzip的模块,它可以节省您不必考虑像文本模式nasssties,在为额外的头信息的几个字节的成本。

如果你一直使用“RB”,并在你的代码压缩在解压缩代码“WB”,但不是[不大可能?],你是不是大清洗,你只需要充实上面的减压代码,并去了。

仔细注意下列未经测试的想法使用“可能”,“应该”,等等。

如果你还没有使用过“RB”,并在压缩编码的WB',你已经大清洗自己的概率是相当高的。

如果你的原始文件有“\ X1A”的任何情况下,任何数据后的第一个此类损失 - 但在这种情况下,它不应该失败的减压(IOW这种情况下不符合您的症状)。

如果按Ctrl-Z是由zlib的本身产生的,这一点应引起在试图解压早期EOF,这当然应该引起异常。 在这种情况下,你可能能够小心翼翼逆转这一过程通过读取压缩文件中的二进制模式,然后替换“\ r \ N”与“\ n” [即模拟文本模式,而不按Ctrl-Z - > EOF噱头]。 解压缩的结果。 编辑写出来的结果以文本模式。 编辑完

更新2我可以重现你的症状-与任何级别1到9 -与下面的脚本:

import zlib, sys
fn = sys.argv[1]
level = int(sys.argv[2])
s1 = open(fn).read() # TEXT mode
s2 = zlib.compress(s1, level)
f = open(fn + '-ct', 'w') # TEXT mode
f.write(s2)
f.close()
# try to decompress in text mode
s1 = open(fn + '-ct').read() # TEXT mode
s2 = zlib.decompress(s1) # error -5
f = open(fn + '-dtt', 'w')
f.write(s2)
f.close()

注意:您将需要一个使用一个相当大的文本文件(我用了一个80KB的源文件),确保减压结果将包含“\ X1A”。

我可以用这个脚本恢复:

import zlib, sys
fn = sys.argv[1]
# (1) reverse the text-mode write
# can't use text-mode read as it will stop at Ctrl-Z
s1 = open(fn, 'rb').read() # BINARY mode
s1 = s1.replace('\r\n', '\n')
# (2) reverse the compression
s2 = zlib.decompress(s1)
# (3) reverse the text mode read
f = open(fn + '-fixed', 'w') # TEXT mode
f.write(s2)
f.close()

注意:如果有一个“\ X1A”原始文件又名按Ctrl-Z字节,文件读取的文本模式下,字节和所有后续字节将不会包含在压缩文件中,因此无法恢复。 对于文本文件(如源代码),这是没有损失的。 对于一个二进制文件,你是最有可能的大清洗。

更新3 [以下晚启示,有涉及该问题的加密/解密层]:

“错误-5”消息表明您要解压缩数据已经错位,因为它被压缩。 如果它不是通过在文件中使用文本模式造成的,怀疑显然(?)落在你解密和加密的包装。 如果你想帮助,你需要这些泄露包装的来源。 其实你应该尝试做的是(像我一样)把一个小脚本再现上有多个输入文件的问题。 其次(像我一样),看看是否能扭转什么条件下的过程。 如果你想与第二阶段的帮助,你需要泄露问题复制脚本。



Answer 2:

我在寻找

python -c 'import sys,zlib;sys.stdout.write(zlib.decompress(sys.stdin.read()))'

自己写的; 基于对答案在python zlib的减压



Answer 3:

好吧对不起,我不太清楚。 这是Win32,蟒蛇2.6.2。 我怕我找不到zlib的文件,但其无论是包含在Win32的二进制版本。 而且我没有访问原始数据 - 我一直在压缩我的日志文件,我想,让他们回来。 至于其他软件,我已经试过naievely 7zip的,但当然失败了,因为它的zlib而不是gzip(我不能任何软件解压缩zlib的直接流)。 我现在不能追溯的翻版,但它是(追溯到zlib.decompress(数据))zlib.error:错误:-3。 另外,要清楚,这些都是静态的文件,而不是流作为我把它前面的声音(所以没有传输错误)。 我怕我再没有代码,但我知道我用zlib.compress(数据,9)(即最高压缩级别 - 但是,有趣的是这似乎并不是所有的zlib的输出78da如因为我把它放在最高水平,你可能期望),只是zlib.decompress()。



Answer 4:

好吧我的最后一篇对不起,我没有一切。 而且因为我没有使用OpenID的我不能编辑自己的帖子。 不管怎么说,这里的一些数据:

1)减压回溯:

Traceback (most recent call last):
  File "<my file>", line 5, in <module>
    zlib.decompress(data)
zlib.error: Error -5 while decompressing data

2)压缩码:

#here you can assume the data is the data to be compressed/stored
data = encrypt(zlib.compress(data,9)) #a short wrapper around PyCrypto AES encryption
f = open("somefile", 'wb')
f.write(data)
f.close()

3)解压缩代码:

f = open("somefile", 'rb')
data = f.read()
f.close()

zlib.decompress(decrypt(data)) #this yeilds the error in (1)


文章来源: zlib decompression in python