基于huffman树的文件压缩项目以及相关测试

news2024/11/13 8:56:27

前言

  • 项目采用Huffman编码的方式进行文件压缩与解压缩。主要原理是通过Huffman编码来表示字符,出现次数多的编码短,出现次数少的编码长,这样整体而言,所需要的bit位是减少的,就实现了文件压缩功能。
  • 读取文件中的字符出现次数,构建Huffman树,然后解析这个字符的每一位,遇到一个叶子结点,就代表还原了一个字符,这时就将这个字符写到解压缩文件里。
  • 注意当大部分字符出现的频率都差不多时,Huffman压缩的效率比较低。

一、文件压缩简介

1、什么是文件压缩

文件压缩是指在不丢失有用信息的前提下,缩减数据量以减少存储空间,提高其传输、存储和处理效率,或按照一定的算法对文件中数据进行重新组织,减少数据的冗余和存储的空间的一种技术方法。

2、压缩的本质及好处
  • 压缩的目的是让文件变小,减少文件所占的存储空间
  • 紧缩数据存储容量,减少存储空间
  • 可以提高数据传输的速度,减少带宽占用量,提高通讯效率

二、 huffman树简介

1、什么是huffman树?

哈夫曼树是一种带权路径长度最短的二叉树,也称为最优二叉树。
带权路径长度: 从二叉树的根结点到二叉树中所有叶结点的路径长度与相应权值的乘积之和为该二叉树的带权路径长度WPL。

如下图:

上述四棵树的带权路径长度分别为:
  • WPLa = 1 * 2 + 3 * 2 + 5 * 2 + 7 * 2 = 32
  • WPLb = 1 * 2 + 3 * 3 + 5 * 3 + 7 * 1 = 33
  • WPLc = 7 * 3 + 5 * 3 + 3 * 2 + 1 * 1 = 43
  • WPLd = 1 * 3 + 3 * 3 + 5 * 2 + 7 * 1 = 29

将带权路径最小的二叉树称为huffman树,所以图(d)为Huffman树。

2、huffman树构建

由给定的n个权值{ w1, w2, w3, … , wn}构造n棵只有根节点的二叉树森林F={T1, T2 , T3, … ,Tn},每棵二叉树Ti只有一个带权值wi的根节点,左右孩子均为空。
重复以下步骤,直到F中只剩下一棵树为止
1)在F中选取两棵根节点权值最小的二叉树,作为左右子树构造一棵新的二叉树,新二叉树根节点的权值为其左右子树根节点的权值之和
2)在F中删除这两棵二叉树
3)把新的二叉树加入到F中

如图所示:

3、获取huffman编码

三、huffman树和文件压缩的关系

压缩的目的是让文件变小,减少文件所占的存储空间。那怎么才能让文件变小呢?

基于huffman树的文件压缩是从字节方面来进行压缩的,一个字节占用8个比特位,如果能够给一个字节找到更短的编码,即少于8个比特位,就可以起到压缩的目的,编码一般分为:静态等长编码和动态不等长编码。

比如:ABBBBCCCCCDDDDDDD字符串(16个字符占16个字节)

  • 静态等长编码

文件中共有4个不同种类的字符,因此每个字符可以用两个二进制的比特位表示。

用等长编码对上述源数据进行压缩:01101110 11110111 11100011 10011110,压缩完成后的结果只占4个字节,压缩率还是比较高的。

该种压缩方式一般要求文件中字符种类比较少,但是一般情况下文件中字节的种类是比较多的。

  • 动态不等长编码
根据文件中字节的分布情况获取每个字节的编码。使用不等长编码对源数据进行压缩:10111011 00101001 11000111 01011。压缩完成后最后一个字节没有用完,还剩余3个比特位,对于该文件中内容,动态不等长编码方式比等 长编码方式的压缩率能好点。
采用静态等长编码压缩: 00010101 10101010 10000000 00000000
采用动态不等长编码压缩:10010110 11011111 11111100 00000000
源文件16个字节,压缩完成之后占4个字节,可以起到压缩的目的。
上述动态不等长编码有一种方式可以简单获取到,huffman树。

四、 文件的编写思路及流程

1、文件的压缩
  • 打开被压缩文件,获取文件中每个字符串出现的总次数。
  • 以每个字符出现的总次数为权值构建 huffman 树。
  • 通过 huffman 树获取每个字符的 huffman 编码。
  • 读取源文件,对源文件中的每个字符使用获取的huffman编码进行改写(要注意当最后一个字节不满时,需要单独处理 ),将改写结果写到压缩文件中, 直到文件结束,生成一个新的压缩文件。
思考:只是将字符替换成编码就够了吗?假设按照上述操作已经对源文件压缩完毕,怎么解压缩?解压缩之后文件的后缀怎么与源文件保持一致?

       我们可以想一下,当文件压缩完成后随之字符的相关信息也会失效,那么怎样解压呢,没有字符信息就没办法构建对应的哈夫曼树,也就没办法进行解压,因此:压缩文件中除了保存压缩数据外,还必须保存解压缩所需的信息。如文件的类型、每个种字符及出现的次数,当然这些信息最好写在文件的开头,方便我们进行读取。所以得规定压缩文件的格式来获取字符相关信息以帮助我们对文件进行解压缩。

压缩文件格式:

2、文件的解压缩
  • 从压缩文件中获取源文件的后缀来判断文件的类型能否解压。
  • 从压缩文件中获取字符次数的总行数
  • 获取每个字符出现的次数
  • 重建huffman树
  • 解压压缩数据

    • a.从压缩文件中读取一个字节的获取压缩数据ch
    • b.从根节点开始,按照ch的8个比特位信息从高到低遍历huffman树:                                该比特位是0,取当前节点的左孩子,否则取右孩子,直到遍历到叶子节点位置,该字符就被解析成功。将解压出的字符写入文件。如果在遍历huffman过程中,8个比特位已经比较完毕还没有到达叶子节点,从a开始执行。
    • c.重复以上过程,直到所有的数据解析完毕。

五、相关代码链接  

        基于huffman树的文件压缩与解压缩

六、关于huffman树的问题及思考

1、解压缩时解压不完全。由于使用文本形式读取压缩文件,有可能提前遇到文件结束标志,所以要改为二进制形式读写。二进制形式是读取二进制编码。如果以文本形式读取的话,回车会被当成一个字符’\n’,而二进制形式则会认为它是两个字符即’\r’回车、’\n’换行;如果在文本形式中遇到0xFF的话,文本形式会认为这是文本结束符,而二进制则不会对它产生处理。

2、换行问题---因为在对文件进行压缩的时候要保存字节频度信息,保存时用换行符来表示每个信息的结束,所以遇到换行符会进行break,不保存其信息,但是在通过字符品读信息进行解压缩的时候,会读取到换行符,需要对换行符进行单独处理,否则解压缩结果就会错误。

3、压缩汉字时出现问题,因为汉字是由多个字符表示,这些字符的范围是0—255,所以在结构体中要用unsigned char表示。

4、创建huffman树时,因为节点中保存的是一个结构体而不是一个简单的内置类型,因此在对节点进行“比较”操作的时候需要自己重载这些比较操作符。

5、引用问题 ,生成编码的时候  这块加引用就是为了方便,修改chCode就是在修改 _fileInfo[root->_weight._ch]._chCode,主要将生成的编码保存到_fileInfo[root->_weight._ch]._chCode中,压缩的时候才能取到编码信息,即编码的长度不会为0。

6、第一次在对源文件进行huffman树构建的时候,需要对源文件从头读完,所以文件指针就在文件末尾,在第二次需要对源文件进行压缩的时候,需要从头开始进行字符及其对应编码的替换,所以得把文件指针移到文件开头,要不然压缩结果就有问题。

7、huffman树压缩完成后,必须要在压缩文件中保存字节频度信息,才可以解压缩,如果字节的频度信息比较大,对压缩率也会有一定的影响。而且解压缩时通过不断遍历还原的huffman树来进行解压,对解压的效率 也会有一定的影响。

8、我们在借助Huffman树去生成编码的时候时候会存在前缀编码呢?答案其实是不会的,因为这些权值其实都是处在叶子节点的位置上的,所以说不会有一个结点是另一个结点的前缀,因为只有一个结点在另一个结点的前缀路径中才会是的一个的前缀是另一个的前缀,所以借助Huffman树是不会出现这种情况的。

七、测试

  • 用不同格式的文件测试程序,用beyond compare进行对比是否正确。(注:.hf后缀是压缩后的文件,-huff.文件类型 是对压缩文件进行解压后的文件)                                                             文件压缩与解压缩项目目录 
  1. doc源文件、压缩文件以及解压缩文件源文件、压缩文件以及解压缩文件大小对比用beyond compare对比源文件与解压文件是否相同---所有参数都一样
  2. jpg源文件、压缩文件以及解压缩文件源文件、压缩文件以及解压缩文件大小对比用beyond compare对比源文件与解压文件是否相同---所有参数都一样
  3. md文件源文件、压缩文件以及解压缩文件源文件、压缩文件以及解压缩文件大小对比用beyond compare对比源文件与解压文件是否相同---所有参数都一样
  4. txt文件源文件、压缩文件以及解压缩文件源文件、压缩文件以及解压缩文件大小对比用beyond compare对比源文件与解压文件是否相同---所有参数都一样
  5. docx文件源文件、压缩文件以及解压缩文件源文件、压缩文件以及解压缩文件大小对比用beyond compare对比源文件与解压文件是否相同---所有参数都一样
  • 性能分析
  •  压缩率 = (压缩后文件大小 / 原始文件大小) * 100%
  • 压缩比例 = 原始文件大小 / 压缩后文件大小
  • 节省空间比例 = (原始文件大小 - 压缩后文件大小) / 原始文件大小 * 100%
文件名源文件大小压缩文件大小解压缩后文件大小 压缩率压缩比例节省空间比例
1.txt1kb1kb1kb100%10%
2.md4kb3kb4kb75%0.75025%
3.docx16kb17kb16kb106.3%1.0630%
docfile.doc28kb12kb28kb42.9%0.42957.1%
imagefile.jpg39kb41kb39kb105.1%1.0510%
  • 对压缩文件进行二次压缩
文件名原压缩文件大小二次压缩后文件大小
1.hf1kb1kb
2.hf3kb2kb
3.hf17kb2kb
docfile.hf12kb2kb
imagefile.hf41kb2kb
对压缩文件进行多次压缩
文件名原压缩文件大小三次压缩后文件大小
1.hf1kb1kb
2.hf2kb2kb
3.hf2kb2kb
docfile.hf2kb2kb
imagefile.hf2kb2kb
文件名原压缩文件大小四次压缩后文件大小
1.hf1kb1kb
2.hf2kb2kb
3.hf2kb2kb
docfile.hf2kb2kb
imagefile.hf2kb2kb
  • 总结:
  • 1、Huffman压缩适用于字符出现次数差值较大,分布不平均的文件。
  • 2、对于文件多次压缩意义不大。
  • 3、不能压缩文件夹,只能对单个文件进行压缩和解压缩。
  • 4、从测试来看,能够处理大部分文件较好性能的压缩。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2116604.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于大语言模型智能体的自主机器学习

文章介绍了MLR-Copilot框架,这是一种利用大型语言模型(LLMs)来自动化机器学习研究中创意生成、实验设计和实施过程的方法。该框架分为三个阶段: 首先通过阅读现有研究文献,使用LLM驱动的IdeaAgent来生成研究假设和实验…

PADS Router 入门基础教程(一)

有将近三周没有更新过博客了,最近在整理PADS Router 入门基础教程,希望喜欢本系列教程的小伙伴可以点点关注和订阅!下面我们开始进入PADS Router课程的介绍。 一、PADS Router 快捷键 ​ 二、课程介绍 本教程主要介绍:PADS Rou…

电脑安装Winserver2016无法安装网卡驱动(解决办法)

因为工作原因,需要找一台PC机作为服务器去测试软件性能问题,故需要在PC机上安装网卡驱动。 电脑品牌:联想 型号:天逸510Pro-18ICB 操作系统:WindowsServer2016(桌面版) 问题:系统…

连接池-druid

原因:通过jdbc 创建Connection时比较耗费资源和时间,如果程序每次执行数据库操作都自己创建连接,项目不好控制连接数量,另外程序执行相对耗时。 市面上有很多厂商有连接池组件,目前比较出名的是alibaba druid 以及 Hi…

828华为云征文|华为Flexus云服务器快速上手实例安装“运维搭子”

⭐ 引言 华为云Flexus X实例简介 在现代云计算的世界里,资源的灵活性和性能至关重要。华为云Flexus X实例正是为满足这一需求而诞生的,它代表了云服务器技术的新高度 🌐🚀。 华为云Flexus X实例采用了领先的擎天QingTian架构&a…

计算机毕业设计 沉浸式戏曲文化体验系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…

深入探索嵌入式 Linux

摘要:本文深入探究嵌入式 Linux。首先回顾其发展历程,从早期尝试到克服诸多困难逐渐成熟。接着阐述其体系结构,涵盖硬件、内核、文件系统和应用层。开发环境方面包括交叉编译工具链、调试工具和集成开发环境。在应用领域,广泛应用…

uniapp设置微信小程序的交互反馈

链接:uni.showToast(OBJECT) | uni-app官网 (dcloud.net.cn) 设置操作成功的弹窗: title是我们弹窗提示的文字 showToast是我们在加载的时候进入就会弹出的提示。 2.设置失败的提示窗口和标签 icon:error是设置我们失败的logo 设置的文字上…

探探我对加密算法的认识

密码学基本认知 为什么需要加密算法,如果不加密可能导致哪些问题? 如果对传输的数据不使用加密算法,所有的数据在传输过程中都是明文传输的,那么会出现以下三种问题: 1)泄露问题:如果在网络中…

大美祖国之地名篇-探寻全国同名地名

目录 前言 一、地名数据库 1、数据库模型 2、数据表结构 二、实践之旅,发现同名地名 1、省、市同名 2、市、县同名 3、 区县、乡镇同名 4、乡镇和村委会同名 三、总结 前言 我们祖国地大物博,从北到南,从东到西。祖国位于亚洲东部&…

SigLIP——采用sigmoid损失的图文预训练方式

SigLIP——采用sigmoid损失的图文预训练方式 FesianXu 20240825 at Wechat Search Team 前言 CLIP中的infoNCE损失是一种对比性损失,在SigLIP这个工作中,作者提出采用非对比性的sigmoid损失,能够更高效地进行图文预训练,本文进行…

信创企业级即时通讯:私有化安全沟通的新趋势

随着信息技术的不断发展,企业间的及时沟通和高效协作成为了推动业务创新和发展的关键。而信创企业作为信息创新的先驱者,对即时通讯工具的安全性和私有化能力提出了更高的要求。在这样的背景下,私有化安全沟通逐渐成为了信创企业级即时通讯的…

特殊类设计与单例模式

特殊类设计与单例模式 一、不能被拷贝的类1、介绍2、示例代码 二、只能在堆上创建对象的类1、介绍2、示例代码 三、只能在栈上创建对象的类1、介绍2、示例代码 四、单例模式1、介绍2、设计模式3、懒汉式(1)介绍(2)示例代码1&#…

Android 12 SystemUI下拉状态栏禁止QuickQSPanel展开

1.概述 遇到需求,QuickQSPanel首次下拉后展示快捷功能模块以后就是显示QuickQSPanel,而不展开QSPanel,接下来要从下滑手势下拉出状态栏分析功能实现。也就是直接是展开状态。 2、涉及核心类 frameworks\base\packages\SystemUI\src\com\and…

STL经典案例(四)——实验室预约综合管理系统(项目涉及知识点很全面,内容有点多,耐心看完会有收获的!)

项目干货满满,内容有点过多,看起来可能会有点卡。系统提示读完超过俩小时,建议分多篇发布,我觉得分篇就不完整了,失去了这个项目的灵魂 一、需求分析 高校实验室预约管理系统包括三种不同身份:管理员、实…

【C++】手把手教你看懂的 STL map 详解(超详细解析,小白一看就懂!!)

目录 一、前言 二、预备知识 💢关联式容器💢 💢键值对💢 💢哈希结构的关联式容器💢 三、map 详解 🔥map 的介绍 🔥map的模板参数说明 🔥map的构造…

HarmonyOS应用开发( Beta5.0)HOS-用户认证服务:面部识别

介绍 User Authentication Kit(用户认证服务)提供了基于用户在设备本地注册的人脸和指纹来认证用户身份的能力。 用户向应用/系统服务请求访问某些个人数据或执行某些敏感操作时,应用/系统服务将调用系统用户身份认证控件对用户身份进行认证…

AI在医学领域:MIL回归用于前列腺癌复发预测

2024年,全球男性新癌症病例预计为1029080例,其中前列腺癌病例预计为29%。前列腺癌是男性中第二常见的癌症类型,仅次于肺癌。它主要影响老年男性,且发病率随年龄增长而增加。前列腺癌的主要治疗方法是前列腺切除术,但术…

知识竞赛答题软件应用场景有哪些

知识竞赛答题软件应用常见场景有哪些? 一、场景分析:该答题软件基于java技术和原生小程序开发完成,其功能主要包括:个人答题、好友pk、排位pk升级赛、专题pk答题、多人pk答题、积分兑换、排行榜等七大功能模块页面,适用…

记一次学习--内网穿透

目录 环境搭建 两张网卡如何配置 Ubuntu配置 渗透 ubuntu的拿下 centos的拿下 探测内网环境 fscan扫描 msf上马 渗透 拿下bage cms windows的拿下 ​编辑 使用fscan查看内网环境,发现了192.168.110.128这台设备 使用msf上马,现在这台机器是…