一、前言
文件在磁盘(等外存设备)上是如何被存储的,这是一个程序猿所必备的知识,有时会作为冷门的考点被加入到面试中来,下面跟着无神一起来学习文件在计算机上的压缩原理!
二、文件的存储形式
在计算机中,数据都是以字节流的形式进行存储和处理的,文件作为数据的一种形式也不例外。
文件就是字节数据的集合。用 1字节( = 8bit = 8位 )表示的字节数据有 256 种。用二进制数表示的话,其范围就是 0000 0000 - 1111 1111 。如果文件中存储的数据是文字,那么该文件就是文本文件。如果是图形,那么该文件就是图像文件。
在任何情况下,文件中的字节数据都是连续存储的。
三、RLE算法
把文件内容用 “数据 x 重复次数” 的形式来表示的压缩方法称为 RLE(Run Length Encoding , 行程长度编码)算法。
四、RLE算法的局限
然而,在实际的文本文件中,同样字符多次重复出现的情况并不多见。虽然针对相同数据经常连续出现的图像、文件等,RLE 算法可以发挥不错的效果,但它并不适合文本文件的压缩。因为,文本文件中同样字符连续出现的部分并不多,因此,使用 RLE 算法后,大部分字符后面都会加上 1 ,这样一来,压缩后的文件自然变成了之前的 2 倍。
五、压缩技巧——霍夫曼编码(与数据结构进行一个交叉)
4.通过莫尔斯编码来看哈夫曼算法的基础
压缩技巧实际上有很多种。接下来,我们就来看一下本章要介绍的第二个压缩技巧,即哈夫曼算法。日本人比较常用的压缩软件 LHA ,使用的就是哈夫曼算法。
其核心思想就是将出现频率高的字段用较短的序号进行编码,从而能够减少最终的码的长度,因此,能够在文件压缩领域取得比较好的性能。
而且是最短前缀码,即每一个编码都不是其他编码的前缀,这部分内容学过数据结构和离散数学的同学们应该非常熟悉。
文本文件是由不同类型的字符组合而成的,而且不同的字符出现的次数也是不同的。而哈夫曼算法的关键就在于“多次出现的数据用小于8位的字节数来表示,不常用的数据则可以用超过8位的字节数来表示” 。不过有一点需要注意,不管是不满 8 位的数据,还是超过 8 位的数据,最终都要以 8 位为单位保存到文件中。这是因为磁盘是以字节(8位)为单位来保存数据的。为了实现这一原理,压缩程序内容会复杂很多,不过作为回报,最终得到的压缩率也是相当高的。
使用哈夫曼树后,出现频率越高的数据所占用的数据位数就越少,而且数据的区分也可以很清晰地实现。但哈夫曼算法为什么达到这么好的效果呢,大家都了解吗?
通过上图步骤2可以发现,在用枝条连接数据时,我们是从出现频率较低的数据开始的,这就意味着出现频率越低的数据到达根部的枝条数就越多。而枝条越多,编码的位数也就随之增多了。
而从用哈夫曼算法压缩过的文件中读取数据后,就会以位为单位对该数据进行排查,并与哈夫曼数进行比较看是否达到了目标编码,这就是为什么哈夫曼算法可以对数据进行区分的原因。例如,10001这个使用上图哈夫曼编码作成的 5 位数据,到达 100 时,对照哈夫曼树的数据,该数据表示的是 B 这个字符。至此就找到了 1 个字符。然后再顺着哈夫曼树寻找剩下的 01 ,会发现它表示的是 E 这个字符。
接下来,让我们来看一下哈夫曼算法的压缩比率。用哈夫曼编码表示 AAAAAABBCDDEEEEEF,结果为 0000000000001001001101011010101010101111, 40 位 = 5 字节。压缩前的数据是 17字符 = 17 字节 ,也就是说,我们得到了 5 字节 ÷ 17 字节 ≈ 29% 这样高的压缩率。
六、可还原压缩和不可还原压缩
有的如图像之类的压缩以后再还原会有损失,这也解释了为什么有的图片经过传输之后会变得更模糊(其经过压缩之后再还原具有数据损失)。