【项目】文件的压缩与解压

项目平台

Windows     VS2013    Beyond Compare4

项目技术

  • Huffman树
  • 优先级队列

项目描述

  • 统计文件中每个字符出现的次数,根据优先级对列,构建Huffman树,出现次数多的编码短,出现次数少的编码常
  • 根据构建好的Huffman树,对文件进行压缩
  • 在对压缩好的文件进行解压,判断争取行。

项目原理

Hffman树,又称为最有二叉树,是加权路径长度最短的二叉树。
  • 利用贪心算法构建Huffman树,可以做出当前看看起来最好的选择。
    【项目】文件的压缩与解压_第1张图片
  • 生成Huffman编码
    【项目】文件的压缩与解压_第2张图片
    我们可以看到,对应权值小的编码长,权值大的编码短,文件压缩正是用的这一边,一个文件里出现次数多的,它的编码就短,这样才可以节省空间,起到压缩的目的。
文件压缩原理

假设我们有一个文件,里边存的是

aaaabbbccd

我们要对这个文件进行压缩,首先我们可以看出,a出现了4次,b出现了3次,c出现了2次,d出现了一次。我们来根据次数建Huffman树,
【项目】文件的压缩与解压_第3张图片
如图生成了Huffman编码,
对应的源文件,转换成编码后,

00001010 10111111 110

不够8个bit位,要不齐,因此补完之后就占3个字节,而原文件占10个字节,这就是文件压缩的原理。

项目的主要思路

【项目】文件的压缩与解压_第4张图片

项目过程

文件压缩过程

先统计每个字符出现的次数,然后用次数来构建Huffman树,根据Huffman树将文件转换为对应的Huffman编码,不够的位补0。

具体过程:

  • 读取文件,将每个字符,该字符出现的次数和权值构成哈夫曼树;
  • 哈夫曼树是利用小堆构成,字符出现次数少的节点指针存在堆顶,出现次数多的在堆底;
  • 每次取两个最小的值,将两数相加的结果作为父结点,构成一颗二叉树,然后在该值放入堆中 ,直到堆被取完,这时Huffman树也构构建完成
  • 从Huffman树中获取Huffman编码,然后根据字符数组,获取每个字符出现的次数
  • 获取编码后,每次凑够8位写入压缩文件中
文件解压过程

先构建Huffman树和Huffman编码,然后统计Huffman树的叶子结点的之后,对应的就是原文件中的字符个数,然后根据压缩文件里的Huffman编码去获取字符,再将字符写入解压文件中。

具体过程:
- 构建Hufman树和Huffman编码
- 根据所有叶子结点之后,算出字符的总个数
- 读取压缩文件,根据文件的编码找到对应的字符,将字符写入到解压文件
- 用Beyond Compare4 进行对比,判断正确性

项目测试

【项目】文件的压缩与解压_第5张图片
【源文件大小】:

项目中碰到的问题

  • 测试的时候发现如果待压缩文件中出现中文,程序就会崩溃

将错误定位到构造哈弗曼编码的函数处,通过单步调试发现是数组越界所致,因为如果只是字符,它的范围是-128~127,程序中通过一个char类型的变量作为数组的下标(0~127),是没有问题的,但汉字的编码是两个字节(只能收录2万多的汉字,但在本项目中已经够用了,这里不进行深究),所以会发生数组越界,解决方法是将char强转为unsigned char,可表示范围为0~255。

  • 怎样判断压缩后的编码有没有补充位?

根据解压时构建的Huffman树,算出其叶子结点之和,根据叶子节点值就是总共压缩的字符个数,

  • 文件的打开方式。

这里打开文件一定要用二进制形式,”wb”,”rb”.因为二进制打开和文本打开其实是有区别的。文本方式打开,会对‘\n’进行特殊处理,那如果这个字符本身就是’\n’.这就会出现问题,所以使用二进制打开,特点:不进行任何处理,是什么就是什么。

  • 文件越压越大

    堆建错了,小堆建成大堆。

不足之处

  • Huffman编码的与缺点就是,只有同样字符出现次数多,和字符出现少的差距大时,才能明显的看到文件被压小,如果,源件里的字符出现的频率都差不多,则起不到作用。
  • 压不了图片,只能压缩文本文档

项目源代码

https://github.com/whiltes/Huffman

你可能感兴趣的:(小项目)