【问题标题】:Re-compress a decompressed string with zlib使用 zlib 重新压缩解压后的字符串
【发布时间】:2019-04-04 20:32:48
【问题描述】:

我有一个编码字符串,我设法在不知道它最初是如何编码的情况下对其进行解码。这就是我设法解码的方式:

original_str = "LONG_SNIP" # Is clearly a base64 string
decoded_str = base64.b64decode(original_str) # Becomes unreadable mess
decompressed_str = zlib.decompress(decoded_str, -15) # Plain text, success

我想指出 zlib 参数 '-15' 是强制性的(在 -8 和 -15 之间有效)

但是,如果我想将纯文本字符串编码为完全相同的格式,以便上面的代码也能成功解码,我会遇到问题。

我检查了 zlib 文档并尝试了 zlib.compress,以及创建了一个 compressobj 并尝试使用它进行压缩,但没有成功。

这个'-15'值好像不能输入到任何函数中来逆转我原来做的解压。

这也是我尝试过的,但我得到的是空白输出:

compress = zlib.compressobj( 1, zlib.DEFLATED, -15, zlib.DEF_MEM_LEVEL, 0 ) 
deflated = compress.compress(string_to_compress)
encoded = base64.b64encode(deflated)
print(encoded)

问题:

整数参数是什么意思,为什么 -8 和 -15 之间的所有值都给出完全相同的输出?

更重要的是,我怎样才能逆转我的减压?

非常感谢您的回答,谢谢!

【问题讨论】:

  • 你找到documentation for zlib.decompress()了吗?它准确地解释了第二个参数的用途,并指出zlib.compressobj() 也接受了wbits 参数。
  • 我确实找到了文档。这也是我也尝试过的,但我得到了空白输出:compress = zlib.compressobj( 1, zlib.DEFLATED, -15, zlib.DEF_MEM_LEVEL, 0 ) deflated = compress.compress(string_to_compress) encoded = base64.b64encode(deflated) print(encoded)
  • .compress() 方法将数据添加到对象并返回一个压缩块如果可用。您需要致电.flush() 来完成压缩过程。
  • 请将该信息添加到您的问题中,这将帮助每个人更好地了解您的上下文。您发现该文档也很有帮助,但请在问题中包含该文档。这就是How to Ask 指南的跟踪您的发现部分; Jon Skeet 的 article on writing the perfect question(链接自 How to Ask)明确呼吁描述您已经尝试过的内容以及任何研究的结果

标签: python python-2.7 compression zlib


【解决方案1】:

zlib.decompress() 的第二个参数是 wbits 参数。来自documentation

wbits 参数控制历史缓冲区的大小(或“窗口大小”),以及预期的标头和尾标格式。它类似于compressobj()的参数,但接受更多范围的值:

  • [...]
  • -8 到-15:使用 wbits 的绝对值作为窗口大小的对数。输入必须是没有标头或尾标的原始流。
  • [...]

解压流时,窗口大小不得小于最初用于压缩流的大小;使用太小的值可能会导致error 异常。

负值仅表示数据流中没有标头或尾标。

因此,如果 -8 和 -15 之间的任何值有效,则压缩的窗口大小开始时非常小。更大的窗口大小需要更多内存用于更大的历史缓冲区,但会使解压缩速度更快。唯一的要求是它应该等于或大于用于压缩数据的那个,因为否则无法再找到对压缩流中使用的先前数据块的引用(我想,我确定 Mark Adler如果我错了会纠正我)。

zlib manual 似乎暗示wbits=8 实际上会自动替换为wbits=9,并且大概-8 也会发生同样的情况。

这转换为 -9 和 -15 之间的 zlib.compresobj() wbits 值;再次从文档中:

  • -9 到 -15:使用 wbits 的绝对值作为窗口大小的对数,同时生成没有头或尾校验和的原始输出流。

用最小的窗口大小压缩就足够了:

compressor = zlib.compressobj(-1, zlib.DEFLATED, -9)
compressed = compressor.compress(data_to_compress) + compressor.flush()

演示:

>>> import zlib
>>> compressor = zlib.compressobj(-1, zlib.DEFLATED, -9)
>>> compressor.compress('foo bar baz') + compressor.flush()
'K\xcb\xcfWHJ,\x02\xe2*\x00'
>>> zlib.decompress(_, -8)
'foo bar baz'

【讨论】:

    猜你喜欢
    • 2016-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    相关资源
    最近更新 更多