7-zip Deflate与zlib.compress()的差异及相关技术问题咨询
背景
我在理解Deflate压缩机制时遇到了困惑,查阅7zip源码但因可读性差,没找到负责Deflate压缩的函数。准备了两个文本文件:
- Test1.txt内容:
Helo everyone
I am trying to understand Deflate compression but from what i have seen i think i have misunderstood or done something wrong.
So i grabbed a source code for 7zip so i might understand what is happening but the source code is hard to read and i couldn't find the function responsible for Deflate compression
but here is what's troubling me.
- Test2.txt是Test1的截断版本:
Helo everyone
I am trying to understand Deflate compression but from what i have seen i think i have misunderstood or done something wrong.
So i grabbed a source code for 7zip
用以下Python代码调用zlib.compress()压缩Test1.txt:
import zlib def deflate_file(input_filename, output_filename): with open(input_filename, 'rb') as input_file: data = input_file.read() compressed_data = zlib.compress(data, zlib.Z_BEST_COMPRESSION) with open(output_filename, 'wb') as output_file: output_file.write(compressed_data) input_file = 'test1.txt' output_file = 'compressed.deflate' deflate_file(input_file, output_file)
得到的十六进制输出:
78 DA 6D 50 BD 6E 03 21 0C DE 4F BA 77 F0 96 2D 6B 5F A0 43 3B F7 09 E0 F0 81 D5 C3 46 06 12 25 4F 5F 3B 69 A5 56 EA 06 F6 F7 EB 37 3C 04 F0 82 7A 13 C6 75 59 97 77 08 15 86 DE 88 33 0C 81 C9 09 B5 8F C0 09 5E 71 3F C2 40 D8 A4 36 C5 DE 49 18 E2 1C B0 AB 54 B8 96 30 80 A0 84 0B 42 47 64 7B 8F 42 FC F9 33 AB D4 BF A5 44 12 88 42 32 3F E8 52 D1 61 19 AE 2A 9C CF EB F2 21 C6 C8 1A 62 C4 04 C1 00 53 37 B7 4C 08 BB B1 5E EE D4 6C 68 98 4A B9 8C DF F1 9E 09 BA D9 B5 86 EC 9A 1E 6E 14 FC 23 F2 00 68 F2 6A 8A C1 2C 8C 49 B6 9A 47 E2 93 75 21 FB 3B 67 9F BC 0D 6F 68 4D 9B 70 A7 78 3C 13 FC 73 85 75 71 A7 82 FA 90 F7 1C A7 6E 27 94 19 0F 8F 51 F1 FC 05 8F 38 80 56
用7zip压缩该文件得到的十六进制输出:
50 4B 03 04 14 00 00 00 08 00 72 8C 4C 58 BF BE E6 4C D7 00 00 00 66 01 00 00 09 00 00 00 74 65 73 74 31 2E 74 78 74 6D 50 3B 52 03 31 0C ED 77 66 EF A0 2E 5D 5A 2E 40 01 35 27 F0 AE B5 B6 07 5B F2 C8 72 32 E1 F4 48 09 0C 14 E9 6C E9 7D F5 86 95 01 2F 28 37 26 5C 97 75 79 87 D0 40 E5 56 28 81 32 4C 8A 28 43 03 45 78 C5 A3 06 45 D8 B9 75 C1 31 0A 13 6C 53 E1 10 6E 70 CD 41 A1 40 0E 17 84 81 48 F6 D6 5C E8 F3 77 D6 CA F8 91 62 8E C0 02 D1 FC 60 70 43 87 25 B8 0A 53 3A AF CB 07 1B 23 49 D8 36 8C 10 0C 30 65 77 CB 88 70 18 EB E5 AB 74 1B 1A A6 95 94 F5 7F BC 47 82 61 76 BD 23 B9 A6 87 D3 EC 2E 7F 22 77 80 44 AF 26 18 CC C2 98 C5 56 B3 46 3A 59 97 62 7F E7 1C 93 76 F5 86 D6 B4 33 8D B2 D5 47 82 27 57 58 17 77 CA 28 77 79 CF 71 1A 76 42 9E 5B F5 18 0D CF DF 50 4B 01 02 3F 00 14 00 00 00 08 00 72 8C 4C 58 BF BE E6 4C D7 00 00 00 66 01 00 00 09 00 24 00 00 00 00 00 00 00 20 00 00 00 00 00 00 00 74 65 73 74 31 2E 74 78 74 0A 00 20 00 00 00 00 00 18 00 2F 80 43 1F C9 5D DA 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 50 4B 05 06 00 00 00 00 01 00 01 00 5B 00 00 00 FE 00 00 00 00 00
技术问题与解答
1. zlib.compress()与7zip的Deflate压缩存在哪些差异?
- 容器格式不同:zlib输出的是带zlib头(
78 DA)的纯Deflate压缩流;7zip输出的是完整ZIP格式文件,包含文件名、时间戳等元数据和ZIP目录结构,Deflate压缩数据只是其中的一段内容。 - 压缩参数细节差异:两者在滑动窗口大小、霍夫曼树生成策略、块分割逻辑等算法细节上有不同实现。7zip的Deflate有自研优化逻辑,和zlib的最优压缩参数不完全匹配。
- 校验机制不同:zlib用Adler-32校验并嵌入在压缩流末尾;ZIP格式中Deflate数据的校验是单独的CRC32字段,放在ZIP元数据区域,应用场景和位置都不一样。
2. 如何通过zlib实现与7zip一致的压缩输出?
完全一致难度较高,但可以通过以下步骤缩小差异:
- 提取7zip的纯Deflate流:从7zip生成的ZIP文件中剥离容器结构,取出核心的Deflate压缩数据段。
- 匹配压缩参数:
- 确认7zip的Deflate参数:比如32KB滑动窗口、最优压缩级别、动态霍夫曼树等。
- 在zlib中用
zlib.compressobj()手动配置:设置wbits=15(纯Deflate流,不带zlib头)、level=zlib.Z_BEST_COMPRESSION,关闭zlib特有优化项。
- 保证输入一致性:确保输入文件的二进制内容完全相同(比如换行符格式、编码、末尾字节),微小输入差异会导致压缩输出完全不同。
- 模拟ZIP容器:如果需要和7zip的ZIP输出一致,用Python的
zipfile模块生成符合ZIP规范的文件,将zlib压缩的Deflate流写入对应位置,匹配7zip的元数据格式(如压缩方法标记、文件属性)。
3. 为何7zip对Test1.txt和Test2.txt的Deflate输出最高有效位与输入不同?
Deflate的输出是变长比特流,最终会填充0比特凑整字节,这些填充比特会影响输出字节的最高有效位。另外,7zip的Deflate实现在霍夫曼编码的比特排序、块结束标记处理上,和输入字节的位没有直接映射关系——Deflate是基于数据流的统计编码,不是对位的直接转换,所以输出字节的位分布和输入没有一对一对应逻辑。
4. 能否在7zip源码中添加保存Deflate压缩数据的功能以用于分析?
可以,具体步骤:
- 定位Deflate核心代码:7zip的Deflate实现位于
CPP/7zip/Compress/Deflate目录,核心文件是Deflate.cpp和Deflate.h,CDeflateCompress::Write或Finish函数负责生成压缩流。 - 添加保存逻辑:在压缩数据写入输出缓冲区的位置(比如
Flush或Finish函数中),增加代码将纯Deflate压缩数据写入单独的文件。 - 编译测试:用7zip的官方编译环境(如VS、MinGW)重新编译项目,生成新的可执行文件,测试压缩时是否会生成单独的Deflate流文件。
内容的提问来源于stack exchange,提问作者terry franklin

