胡扯
这是对之前的哈夫曼编码–压缩与解压的一个补充说明,这里只做简单的原理介绍,不做过多的具体实现。
写入头文件的必要性
由于不同的文件压缩所用编码不同,必须将对应的编码写入到压缩文件中,才能在解压时还原。
写入头文件的五种方法
头文件不同,所得的文件解压方式不同,大小也会有所不同,甚至会变大。
定义压缩后的文件格式如下图所示,其中蓝绿色块为头文件,其他信息主要存放原文件信息或者编码辅助信息,编码单元存放字符编码后信息,灰色部分为原文件压缩后内容,可见头文件大小取决于编码的存储方式。
为了更好的描述,这里提前做如下定义:
- Total:原文件大小
- Alpha:读取到的字符
- LeafNum:读取到的字符的种类数,在哈夫曼树中作为叶子节点
- Code:字符对应的01编码字符串
- CodeLen:01编码字符的长度
- HufTable:哈夫曼编码的哈希表,为一个一维数组,将Alpha作为下表,Code作为元素的值,用于解压时查找读取到字符的Code。
a. 直接写入字符及编码
直接将字符和编码直接写入压缩文件中。在解压时,获得头文件信息,每读取一个字符,将字符按2进制转化为01字符,再与头文件中的所有的Code 进行比较,找到对应的Alpha写入解压文件中。
b. 统一编码字符长度
将01编码按照每8位压缩为一个字符,有效地减小头文件的大小。压缩之后的头文件如下:
c. 最优编码字符长度
由于用了最长的编码长度,b中方法仍有很多冗余信息。直接按照不同编码的编码长度做最优的长度压缩,如:一段头文件中编码最短为3,最长为36,如果按照b中方法需要将3补全为40再压缩为5个字符,但是这里我们只需要将3补全为8个,压缩为1个字符即可。
其他信息:
因为压缩上需要读取每一个编码的长度,编码补全,编码压缩,压缩后字符个数统计,在解压上需要根据编码信息全长来截取整个头文件,再按照CodeLen,压缩字符长度和压缩字符来对编码信息进行恢复。原文解压同a。
d. 全ASCII字符位置频数法
之前的方法这么说头文件都比较大,而且有的在实现上还很麻烦。这里将给出另一种更简便高效的压缩方式,这也是哈夫曼编码–压缩与解压中采用的方法。
频数的位置对应ASCII码,如第0个频数表示ASCII码为0字符的频数。读取这些频数,可以有效地恢复哈夫曼树,以达到对压缩文件的解压。如果频数用unsigned long格式的数据,就可以记录很大的数据,头文件仅占有2k。
e. 不完全ASCII字符位置频数法
d中方法更加适合于字符种类较多文件,对于字符种类较少的文件,如77种字符,却要用256个位置来记录,明显浪费了很多空间。如果我们用0表示有1表示无,用256个0或1可以表示字符有无,256个0或1又可压缩为16个字符,即8个unsigned long数据,便可省下一些空间。
无论如何头文件终究还是很小的,而且按照现在的硬件存储能力,头文件的大小不会占有太大的存储空间。