zlib decompression in python
好的,我有一些通过python(2.6)zlib.compress()函数压缩的数据流。 当我尝试解压缩它们时,其中一些将不会解压缩(zlib错误-5,这似乎是"缓冲区错误",不知道该怎么做)。 起初,我以为我已经完成了,但是我意识到我无法解压缩的所有内容都从0x78DA开始(工作的是0x789C),我环顾四周,这似乎是另一种zlib压缩- 幻数根据所使用的压缩而变化。 我可以用什么解压缩文件? 我在用软管吗?
根据RFC 1950," OK" 0x789C和"坏" 0x78DA之间的区别在于FLEVEL位字段:
1 2 3 4 5 6 7 8 9 10 11 12 | 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. |
"确定"使用2,"不良"使用3。因此,其本身的区别不成问题。
为了进一步了解,您可能考虑为压缩和(尝试的)解压缩中的每一个提供以下信息:什么平台,什么版本的Python,什么版本的zlib库,什么是用来调用zlib模块的实际代码。还应提供来自失败的解压缩尝试的完整回溯和错误消息。您是否尝试过使用任何其他zlib读取软件解压缩失败的文件?结果如何?请说明您要使用的工具:"我在用软管吗?"意味着您无权访问原始数据?它是如何从流传输到文件的?您如何保证数据不被传输破坏?
更新基于您的自我解答中发布的部分澄清的一些观察结果:
您正在使用Windows。 Windows在读写文件时区分二进制模式和文本模式。在文本模式下阅读时,Python 2.x将' r n'更改为' n',在编写时将' n'更改为' r n'。在处理非文本数据时,这不是一个好主意。更糟糕的是,在文本模式下阅读时,' x1a'又名Ctrl-Z被视为文件结尾。
压缩文件:
1 2 3 4 5 6 | # 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() |
要解压缩文件:
1 2 3 4 5 | 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模块,这样可以省去一些麻烦,例如文本模式,但会花费一些字节的额外标题信息。
如果您一直在压缩代码中使用'rb'和'wb'而不在解压缩代码中使用[不太可能?],那么您就不用管了,您只需要充实上述解压缩代码并继续使用即可。
在以下未经测试的想法中,请仔细注意" may"," should"等的使用。
如果您未在压缩代码中使用" rb"和" wb",则使用软管进行压缩的可能性非常高。
如果原始文件中有任何' x1a'实例,则第一个此类文件之后的任何数据都会丢失-但在这种情况下,解压缩时不会失败(IOW,这种情况与您的症状不符)。
如果Ctrl-Z由zlib本身生成,则这将在尝试进行解压缩时导致早期的EOF,这当然会导致异常。在这种情况下,您可以通过以二进制模式读取压缩文件,然后用' n'替换' r n'来谨慎地逆转该过程[模拟文本模式,而无需按Ctrl-Z-> EOF gi头]。解压缩结果。编辑在TEXT模式下将结果写出。结束编辑
更新2我可以使用以下脚本从1到9的任何级别重现您的症状:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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'。
我可以使用以下脚本恢复:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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(' ', ' ') # (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'aka Ctrl-Z字节,并且以文本模式读取该文件,则该字节和所有后续字节将不包含在压缩文件中,因此无法恢复。对于文本文件(例如源代码),这完全没有损失。对于二进制文件,很可能已被清理。
更新3 [后来发现该问题涉及加密/解密层]:
"错误-5"消息表明,您尝试解压缩的数据自压缩以来已被篡改。如果不是由于在文件上使用文本模式引起的,则怀疑显然是由解密和加密包装程序引起的。如果需要帮助,则需要透露这些包装的来源。实际上,您应该尝试做的是(就像我一样)将一个小的脚本放在一起,以便在多个输入文件上重现该问题。其次(就像我一样),看看是否可以在什么条件下撤消该过程。如果您需要第二阶段的帮助,则需要泄漏问题重现脚本。
我正寻找
1 | python -c 'import sys,zlib;sys.stdout.write(zlib.decompress(sys.stdin.read()))' |
我自己写的基于python中zlib解压缩的答案
好的,很抱歉,我的上一篇文章,我没有所有内容。而且由于我没有使用OpenID,所以我无法编辑自己的帖子。无论如何,这里有一些数据:
1)减压回溯:
1 2 3 4 | Traceback (most recent call last): File"<my file>", line 5, in <module> zlib.decompress(data) zlib.error: Error -5 while decompressing data |
2)压缩码:
1 2 3 4 5 | #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)减压码:
1 2 3 4 5 | f = open("somefile", 'rb') data = f.read() f.close() zlib.decompress(decrypt(data)) #this yeilds the error in (1) |
好的,抱歉,我还不够清楚。这是Win32,Python 2.6.2。恐怕我找不到zlib文件,但是无论它在win32二进制发行版中包含什么。而且我无权访问原始数据-我一直在压缩日志文件,所以我想找回它们。至于其他软件,我天真地尝试了7zip,但是当然失败了,因为它是zlib,而不是gzip(我无法使用任何软件直接解压缩zlib流)。我现在不能提供追溯的完整副本,但是它是(追溯到zlib.decompress(data))zlib.error:错误:-3。另外,需要明确的是,这些是静态文件,而不是我之前所说的流(因此没有传输错误)。而且我再次担心我没有代码,但是我知道我使用了zlib.compress(data,9)(即最高压缩级别-尽管有趣的是,似乎并非所有的zlib输出都是78da,因为您可能会期望,因为我将其置于最高级别),而只是zlib.decompress()。