Huffman压缩软件

项目概述

项目的流程

首先先是实现好哈夫曼压缩的逻辑,我分别将压缩和解压缩封装成两个类。接着利用Java的图形界面工具swing构造用户的GUI界面实现主类。

哈夫曼压缩原理

哈夫曼编码是一个01串,所以每一位编码可以用计算机中的最小单位来存储。其的主要思想是将出现频率高的字符放在靠近根的位置,频率低的字符放在远离根的位置,这样就可以实现字符出现的频数与编码的长度成反比,从而更加合理的分配存储空间来实现文件的压缩。然后其构建是自底向上的,故由前边说的原理可知每一次要找出权值最小的两个节点新生出一个父节点,这样逐层往上构建就可以实现哈夫曼树。为了每次找出最小的两个节点,我提前将所有的节点存放在一个最大值堆中,这样就可以以\[O(logN)\]的复杂度找出权值最小的两个节点。构造好后,根据路径左0右1的约定,就可以获得每一个字符的哈夫曼编码。

总而言之

  • 压缩过程:读取文件,统计字节(字符)出现频数,根据频数构建哈夫曼树,获得每个字符的编码,将解压相关信息和编码重写后的字符写入压缩文件;
  • 解压缩的过程:读文件,读取解压相关信息,构建哈夫曼树,获取每个字符的编码,构建编码到字符映射的 HashMap 方便查找,遍历编码翻译成字符,写入解压文件。

由于我的压缩对象是文本,所以我将整个文本看作是字符的集合,由于 ASCII 码只有256个,所以只需要开辟同等大小的数组来记录每一个字符的出现次数作为关键码。

接着由于Java中最小的数据类型是 byte ,所以要通过位操作来讲每一个编码压入位中。然后为了方便之后的解码,还要存入一些必要的信息,比如总的有效字符个数,和有效字符对应的位级哈夫曼编码,多余的bit个数(因为转换成bit后可能不能刚好存入bytes中)。我的压缩后文件的存储结构如下

有效的字符总数(byte) => 有效字符(byte) + 出现频数(Int, 4bytes) => 多余的bit => 原文的编码表示(bytes)

问题思考

  • 字符哈夫曼编码的哈夫曼编码长度可能会大于8呀,这不是更耗空间了吗?

是的,确实会有字符的编码大于8,但由哈夫曼树的性质可知这种字符的出现次数是很少的。相比之下,出现次数更多的字符其长度往往会省下更多的空间,这也就是非均匀地更加合理分配空间。

项目特点

……无……艹,做了这么久发现这个才是重点~

可改进之处

当前只能够压缩文本文件,压缩图片之类的虽然解压可以还原,但是并没有达到体积压小的目的。

项目中遇到的问题

  • 在解压缩后的文本不符合预期的时候,差错比较麻烦

我使用的方法就是在所有可能发生错误的地方打印相关信息,来查找错误。然后先自己设计较为简单的文本样例,自己模拟一遍,然后在程序跑一遍这样检查。接着再进一步用较长的文章来测试,主要方法还是打印出执行过程中的信息来查错。

  • 文本转换成一位位的编码后可能不能刚好被存入bytes中。

不足的位置在后边补零,用一个byte来记录多余了多少个bit

猜你喜欢

转载自www.cnblogs.com/GorgeousBankarian/p/12543615.html
今日推荐