Unix compress 和 LZW

最后更新: 2025-04-04 21:50:25 +0800 +0800
tags: Compression | Unix | Lzw
原文以英文撰写。您正在阅读AI翻译版本。

历史上的 Unix compress 工具会写入通常命名为 .Z 的文件。它使用 LZW 系列字典编码器,而不是 DEFLATE。uncompress 和 zcat 在提供该格式的系统上公开兼容的命令行接口。

LZW 初始化与同步 #

LZW 编码器从单字节字母表的条目开始。它维护当前短语 w,读取下一个字节 k,并在 w + k 位于字典中时继续处理。当该短语不存在时,它输出 w 的代码,添加 w + k,并从 k 开始。解码器输出每个代码对应的字符串;在第一个代码之后,它会添加前一个解码字符串与当前字符串的第一个字节。输入耗尽后,编码器输出其最终短语。因此,编码器和解码器会相差一个代码地添加相同的条目。

常见的 KwKwK 情况发生在某个代码等于下一个字典索引时:解码器会将其展开为 previous + first(previous)。拒绝这种情况会拒绝有效的数据流;接受任何超过下一个索引的代码则会导致字典失去同步。

.Z 位流 #

.Z 数据流以 1f 9d 和一个标志字节开头。低五位指定最大代码宽度,通常为 9 至 16 位。第 7 位启用块模式;其余保留位必须根据实现的兼容性规则进行处理。代码从 9 位开始,当字典达到当前宽度的容量时逐步增加宽度。在块模式下,代码 256 表示 CLEAR:编码器可以输出该代码以丢弃条目,并使用初始字母表重新开始。解码器必须在同一位置重置,然后恢复使用 9 位代码。非块模式数据流没有该重置代码。

代码宽度转换规则属于 .Z 方言的一部分,因此读取器应遵循格式规定的时序,而不是根据下一个代码进行猜测。历史实现对边界情况的处理存在差异;应使用目标 compress 实现进行互操作性测试。

兼容性与操作 #

LZW 专利曾影响 compress 的部署;相关专利已经到期,但旧归档和特定于平台的解码器仍然构成兼容性约束。对于新数据,应使用协议选定的格式。tar 存储文件名和元数据,而压缩器转换的是字节流,因此 .tar.Z 表示使用 .Z 压缩的 tar 归档。

sh
file backup.tar.Z
uncompress -c backup.tar.Z | tar -tvf -
compress -c source.bin > source.bin.Z
zcat source.bin.Z | sha256sum

.Z 格式没有类似 gzip 尾部的强制端到端校验和。解码器可能会从截断或损坏的数据流中生成看似合理的字节,因此在转换后应保留源归档,并验证外部摘要或已知文件长度。Gzip 使用 DEFLATE,并在每个成员中记录 CRC-32 以及未压缩大小,因此对于普通文件传输,损坏报告能力更强;但 gzip 和 .Z 不是可互换的数据流。

参考资料 #

评论

在 GitHub 上阅读或评论(发表评论需要登录)