Python生成LZMA文件未压缩大小字段全0xFF与lzma.exe输出不一致问题
问题原因
你遇到的头字段Uncompressed Size全为0xFF的问题,核心是两个使用错误:
- 你只调用了
LZMACompressor.compress()方法写入了部分压缩数据,没有调用flush()方法获取压缩结束后的剩余数据、结束标记,也没有完成完整的文件头补全逻辑。 - Python
lzma库的FORMAT_ALONE(即LZMA单独文件格式)的流式压缩模式默认假设输入是未知长度的流,所以会把头中的未压缩大小字段填为全0xFF,这个取值在LZMA规范里代表「未压缩大小未知」,解压时读到流结束即可。而7z官方的lzma.exe压缩时默认会计算输入文件的总大小,写入头字段。
修正代码
你可以直接用更简单的lzma.compress便捷接口,自动处理压缩全流程,输出和lzma.exe逻辑对齐的文件:
import lzma input_path = "file_split0_test.bin" output_path = "file_split0_test.lzma" with open(input_path, "rb") as f_in: raw_data = f_in.read() # 指定和lzma.exe -d23匹配的字典大小2^23=8MB compressed_data = lzma.compress(raw_data, format=lzma.FORMAT_ALONE, dict_size=1 << 23) with open(output_path, "wb") as f_out: f_out.write(compressed_data)
也可以用lzma.open的上下文管理器简化写入逻辑:
import lzma input_path = "file_split0_test.bin" output_path = "file_split0_test.lzma" with open(input_path, "rb") as f_in, \ lzma.open(output_path, "wb", format=lzma.FORMAT_ALONE, dict_size=1 << 23) as f_out: f_out.write(f_in.read())
补充说明
如果你坚持用LZMACompressor手动处理流,必须在写完所有输入数据后调用flush(),把剩余的压缩数据和结束标记写入文件:
lzma_machine = lzma.LZMACompressor(format=lzma.FORMAT_ALONE, dict_size=1 << 23) with open(input_path, "rb") as f_in, open(output_path, "wb") as f_out: f_out.write(lzma_machine.compress(f_in.read())) # 必须调用flush补全数据 f_out.write(lzma_machine.flush())
这种模式下未压缩大小字段还是会保留0xFF,但文件本身可以正常解压,不会影响使用。如果需要和lzma.exe的头字段完全一致,优先使用前两种便捷接口即可。
内容的提问来源于stack exchange,提问作者Justin Yau Wei Shun
相关产品推荐
相关产品推荐

