【项目】哈夫曼树的应用:文件压缩

来源:互联网 发布:openwrt手机网络共享 编辑:程序博客网 时间:2024/06/05 07:41

在前几天写了哈夫曼树以及哈夫曼编码的博客:

http://blog.csdn.net/wenqiang1208/article/details/77261906

文件压缩

文件压缩的主要思想是利用哈夫曼编码来实现的,但是得到编码之前我们需要构建这棵树。那么利用什么来构建树呢?!这里,我们需要统计每个字符出现的次数,用次数来构建Huffman-Tree。假设我们现在有一个.txt的小文件,内容是”aaaabbbccd”。字符存在计算机中时以字节为单位的,因此我们需要将这些字符压缩成0、1表示的编码,0和1表示字节中的“位”,这样能大大降低文件的大小。

这里写图片描述

源文件的的大小10个字节,
压缩后一共19个比特位,不足1个字节后面补足0,一共3个字节。

为了实现文件压缩,需要对文件字符信息进行定义

字符信息结构体
包括字符,字符个数,以及字符压缩后的编码。

struct FileInfo{    FileInfo()    : _count(0)    {}    /*FileInfo operator+(const FileInfo& FileInfoRight)//会改变原来的值    {    this->_count += FileInfoRight._count;    return *this;    }*/    FileInfo operator+(const FileInfo& FileInfoRight)    {        FileInfo  temp(*this);        temp._count += FileInfoRight._count;        return temp;    }    bool operator <(const FileInfo& FileInfoRight)const    {        return _count < FileInfoRight._count;    }    bool operator >(const FileInfo& FileInfoRight)const    {        return _count > FileInfoRight._count;    }    bool operator != (const FileInfo& FileInfoRight)const    {        return _count != FileInfoRight._count;    }    std::string _strCode;//存放当前字符压缩后的编码    unsigned char _ch;//当前字符    size_t _count;//统计字符个数};

对文件信息进行压缩时,需要在新文件中写入头部信息,因为进行解压时需要文件信息。

头部信息包括下面三个部分:
扩展名:(就是源文件的后缀名)
编码行数
编码行 (字符:字符个数)

实现文件压缩的步骤:
(1)打开文件,对文件字符信息进行统计。CountFileInfo函数
(2)根据字符出现的个数,构建哈夫曼树,后序遍历哈夫曼树获取字符编码。FillCode函数和_GenerateHuffmanCode函数
(3)进行文件压缩,写入新的文件中;
a、先把头部信息写入新文件的首部(因为进行解压时,需要用到信息)。WriteHead函数
b、遍历源文件,将每个字符的编码信息写入新文件中。CompressCore函数

文件解压

文件解压,根据文件压缩文件,进行还原源文件。
(1)先读取头部信息,重新构建哈夫曼树。
(2)根据字符编码信息,对哈夫曼树进行遍历,叶子结点信息就是字符信息。
(3)将叶子结点信息重新写入文件中。

文件解压时遇到的问题

(1)比如说“aaa”并没有构建哈夫曼树,那么并没有写入编码信息,

解决方法:直接写入字符信息,不需要转码

(2)压缩信息后面 补足的0,可能会被误读成压缩信息。

压缩以后的文件如果不够一个字节大小,会用0来代替空缺的比特位,这样带来的问题就是可能会多解压出字符。以上述的”aaaabbbccd”为例,压缩以后的编码为19比特位:00001111 11110110 100,计算机存储的最小单位为字节,因此这些编码会被存储为00001111 11110110 10000000,后边的五个0对我们来说就是多余的,如果不处理,就会多还原出5个a。

解决方法:给出一个charCount来统计所有字符串的个数,其实也就是根节点的值,每次还原出一个字符后,charCount就-1,直到charCount为0时说明所有字符都已经解压完成。

代码地址
https://github.com/WenQiangW/FileCompress

测试

这里写图片描述

使用BeyondCompared软件进行对比源文件和新还原的文件,看是否还原成功。

在huffman文件压缩下:
压缩一个1.2M左右的文件,能够到压缩0.9M左右,用时0.5秒左右。
压缩一个2.3M左右的文件,能够到压缩1.8M左右,用时0.8秒左右。
压缩一个8.3M左右的文件,能够到压缩6.7M左右,用时3秒。

原创粉丝点击