遇到不熟悉的词,先看这 3 个解释
- 压缩
- 压缩尝试用更省空间的方式表示数据,例如把重复片段及其位置记录下来。接收方按约定解释这些记录;是否能明显缩小,取决于数据规律和使用的方法。
- 无损压缩
- 无损压缩要求解压后能准确还原交给压缩器的数据,不能少一个字符或改一个数值。它适合需要保留原内容的文件,但能省多少空间仍取决于内容本身。
- 有损压缩
- 有损压缩允许舍弃一部分信息,以换取更小的体积。解码后得到的是近似结果;画面或声音能否接受,要结合具体内容和使用场景判断,不能只看文件大小。
一个很大的文本文件压成了很小的压缩包。既然这次能缩小,继续压十次、百次,能不能最终只剩一个字节?关键不在电脑够不够快,而在解压程序是否还能把所有不同的原文件区分开。
压缩是在寻找更短的写法
假设一张纸上连续写着一千个 A,我们可以记成“重复 A 一千次”。这条描述比原文短,而且接收方按约定就能还原。真实压缩器会寻找重复片段或利用不同符号出现的规律;它没有把信息凭空消灭,而是换成更省空间的表示。
但这个约定也要能被理解。“一千次”怎样编码,原文字母恰好包含命令时怎样区分,数据在哪里结束,都需要规则。文件头、长度和校验信息也可能占空间。因此短文件即使有一点重复,节约的部分也未必足以抵消额外开销。
四种输入,装不进三种短标签
把问题缩小:长度恰好为两位的二进制串只有四个,分别是 00、01、10、11。比两位更短的串有哪些?只有空串、0 和 1,总共三个。如果要求四种输入都缩短,又要求能够无损还原,就必须给四张不同纸条安排三个不同标签。
至少两张纸条会撞到同一个标签。解压程序只看到标签,便无法知道应还原哪一张。这就是简单的计数理由:在固定解码规则下,不可能让每一种输入都更短。扩大到更长文件,短表示数量不够的矛盾仍然存在,与使用哪种编程语言无关。
再压一次可能有用,但没有永久折扣
这不意味着第二次压缩绝对不能变小。第一个压缩器可能没找完规律,特定格式也可能留下重复结构;换工具或再次处理,有时仍能省一点。zlib 的技术说明就讨论过特殊重复数据的这种情况,所以“一定毫无效果”同样说得太满。
但每压一次都保证缩小,适用于所有文件的承诺无法成立。已经压得很紧的数据常常没有足够可用的重复,外层格式却还要增加说明。所谓无损,是解压后逐字节相同;若把图片缩尺寸、删细节后变小,那是在改变需要保留的内容,回答了另一个问题。
比较时要把说明书也算进去
你可以准备一份重复文字和一份已压缩文件,用同一个工具记录输入、输出字节数,再解压比较内容。只需小文件就能观察现象,没必要制造巨大压缩包。压缩比应说明分子分母:有人说原大小除以压缩后大小,也有人报节省百分比。
如果一个方案把主要内容藏进共享字典、远端服务器或接收方预装的数据里,小文件并不等于总成本变小。共享数据在真实场景可能很有价值,但比较时要说明谁已经拥有它、用了多少空间。把这些前提写出来,比只展示漂亮的压缩倍数更有意义。
记住这三点
- 无损压缩必须让不同输入可被正确区分,不能保证所有输入都变短。
- 重复压缩可能在特殊数据上继续省空间,也可能因格式开销变大。
- 比较大小时应计算所需说明和外部字典,并检查解压结果是否相同。
别把例子用过头
- 纸条例子证明的是一般限制,不是在实现 ZIP 或 DEFLATE。
- 某一文件难压缩,不代表其中没有任何规律;结果还取决于格式和算法。
自己试一小步
怎样公平比较重复文字、普通笔记和已有压缩文件的压缩效果?
- 各取一份不含个人信息的小文件,记录原始字节数。
- 使用同一种无损压缩方式,保留原件,记录第一次与第二次输出大小。
- 解压到新目录,比较还原内容,写清工具和设置。
做到这些,就算完成
- 记录包含变大或几乎不变的结果,而不是只挑最好的一项。
- 能区分文件总大小、节省字节数和压缩比。
- 没有把删内容、降图片分辨率计入无损压缩效果。
查原始资料
想确认一个细节,先看这份资料对应的部分,不必从头读完所有文档。
- RFC 1951:DEFLATE Compressed Data Format Specification (新标签页)↗
无损压缩不能压小所有输入的计数限制,以及 DEFLATE 的数据块表示。
- zlib Technical Details (新标签页)↗
压缩可能扩张,封装开销、极端重复数据和二次压缩的特殊情况。
找一份资料继续练
先选一项,按下面的范围继续学;不必从头读完整门课程。
游程压缩小画板:连续的黑白格子能怎样简写? (新标签页)↗
只做黑白格子的连续段编码与还原,区分原图位数、编码字符数和实际文件大小。
查看学习准备与访问说明 →