Python中zlib.compressobj压缩结果与原压缩串不一致如何解决
前提澄清
首先明确一个核心逻辑:如果你已经修改了解压后的字节内容,不可能得到和原压缩串完全一致的结果。DEFLATE是无损压缩算法,压缩串和解压结果一一对应,输入字节发生变化时,压缩输出一定和原串不同。如果你只需要压缩后的串和原串格式兼容、能被相同的解压逻辑解析,你当前生成的可正常解压的串已经满足要求。
如果你是指「解压后不做任何修改,压缩回去也无法得到和原串一致的结果」,原因和解决方法如下:
为什么现有方案无法实现需求
zlib的compressobj默认参数和原压缩使用的参数不一致,影响DEFLATE输出的参数远不止压缩级别(level)和窗口大小(wbits)两个:
memLevel:压缩时使用的内存缓冲区大小,取值范围1~9,默认值为8。该参数控制内部滑动窗口的匹配效率,值越小生成的压缩块越小,输出结果差异越大。strategy:压缩策略,默认值为zlib.Z_DEFAULT_STRATEGY,可选值包括zlib.Z_FILTERED、zlib.Z_HUFFMAN_ONLY、zlib.Z_RLE、zlib.Z_FIXED,不同策略对重复字符串的匹配逻辑、哈夫曼编码表的生成规则完全不同,直接影响最终输出。- zlib版本差异:不同版本的zlib库对压缩逻辑有细微调整,就算所有参数完全一致,不同版本的输出也可能存在差异。
- 自定义字典:如果原压缩时传入了自定义的预设字典,你压缩时没有传入完全相同的字典,输出肯定不一致。
如何得到和原串完全一致的压缩结果
仅适用于解压后未修改内容的场景,按以下步骤操作:
- 先对齐zlib版本:通过
zlib.ZLIB_VERSION查看你当前使用的zlib版本,和原压缩环境的版本保持一致。 - 全参数遍历测试:把
memLevel(1~9)和strategy(所有可选枚举值)加入遍历组合,和你之前试过的level、wbits做全排列测试,完整的压缩对象构造代码参考:comp_obj = zlib.compressobj( level=level, method=zlib.DEFLATED, wbits=wbits, memLevel=memLevel, strategy=strategy ) comp = comp_obj.compress(decompressed) comp += comp_obj.flush() - 如果以上所有组合都无法匹配原串,说明原压缩使用了自定义字典,你需要拿到原压缩时使用的字典字节串,传入
compressobj的zdict参数即可。
内容的提问来源于stack exchange,提问作者anemic_entertainment
相关产品推荐
相关产品推荐

