精华内容
下载资源
问答
  • 号称现最高压缩比的压缩软件,非常好用。
  • UHARC 是一个压缩文件的软件,对应的固有压缩格式为 UHA,其超强压缩比可让 RAR、7Z 等汗颜,其特长是对多媒体文件的压缩。UHARC GUI 则是 MuldeR - LameXP 的作者为 UHARC 开发的一款图形界面前端,已经内部集成了 ...
  • 录屏软件,清晰度和压缩最高软件网上什么kk录像,录屏大师都要好,解压即用,无需注册
  • Zip 是一款号称有着现今最高压缩比的压缩软件,它不仅支持独有的 7z 文件格式,而且还支持各种其它压缩文件格式,其中包括 ZIP, RAR, CAB, GZIP, BZIP2和 TAR 等等。此软件压缩的压缩比要比普通 ZIP 文件高 30-50% ...
  • paq8px据说是一款顶级的高压缩比压缩软件,其压缩率比7-zip还要高上很多,经过实际测试对比paq8p,paq8pxd等格式,得出结论paq8px压缩比最好,并且比早期版本压缩率更高一些。拥有最慢的压缩时间,最高的压缩算法。
  • Zip 现今最高压缩比压缩软件 <br>7-Zip是一款GNU/LPGL协议下分发的免费软件,可以说是目前最有希望成为zip、rar之后的下一个主流压缩格式的文件压缩格式了.7zip的压缩率是他最大的竞争优势,在选择普通压缩率的...
  • PAQ是世界上压缩比最高的压缩算法,其性能远超WinUPX、7z、rar等高压缩比格式文件。FastPAQ是由c++开发的开源软件,它在paq算法原有的压缩比上加快其速度,使其具有更强的用户体验感。它可以用来打开或创建fp8格式的...
  • 7-Zip是一款号称有着现今最高压缩比的压缩软件,它不仅支持独有的 7z 文件格式,而且还支持各种其它压缩文件格式,其中包括 ZIP, RAR, CAB, GZIP, BZIP2和 TAR 等等。此软件压缩的压缩比要比普通 ZIP 文件高 30-50% ...
  • Zip 是一款号称有着现今最高压缩比的压缩软件,它不仅支持独有的 7z 文件格式,而且还支持各种其它压缩文件格式,其中包括 ZIP, RAR, CAB, GZIP, BZIP2和 TAR 等等。此软件压缩的压缩比要比普通 ZIP 文件高 30-50% ...
  • 开源软件,比winrar压缩比高,简爽的界面 最新版
  • 公司有一个DOS启动盘,要增加一个自己编制的程序进去,捣鼓了一下,才发现压缩比最高软件竟然是:makecab.exe通过它制作的压缩软件是不可添加文件的。如果需要添加文件,只能够解压缩后再重新添加文件压缩。在制作...
    公司有一个DOS启动盘,要增加一个自己编制的程序进去,捣鼓了一下,才发现压缩比最高的软件竟然是:makecab.exe
    
    通过它制作的压缩软件是不可添加文件的。如果需要添加文件,只能够解压缩后再重新添加文件压缩。
    在制作的过程中,特别感谢百度的 kivia,因为它的答案就是全部的东西:
    makecab 是个命令
    makecab 的使用方法详解与技巧
    最简单的用法:
    makecab 文件完整的名称 如 makecab wmd.dll
    指定压缩类型及使用内存的大小:
    makecab /d compressiontype=lzx /d compressionmemory=21 wmd.dll 压缩比高
    批量压缩的办法:
    for %v in (*.*) do makecab %v
    之前俺研究了好久,都不知道怎么用一条命令将一个目录下的所有文件压缩成CAB包,现在终于知道了,呵
    压缩成一个CAB包的办法:
    type list.txt (生成一个文件列表)
    makecab /f list.txt /d compressiontype=mszip /d compressionmemory=21 /d maxdisksize=1024000000 /d diskdirectorytemplate=dd* /d cabinetnametemplate=dd*.cab
    来个高压缩比的。呵
    makecab /f list.txt /d compressiontype=lzx /d compressionmemory=21 /d maxdisksize=1024000000 /d diskdirectorytemplate=dd* /d cabinetnametemplate=dd*.cab
    ========================================================
    总共1.03MB的文件,即使采用WinRAR最高压缩,文件大小也还有550K,用了makecab制作后的大小仅为181K,强啊!
    展开全文
  • -Zip 软件基于 GNU 次要公共许可协议(Lesser General Public License) 之下发布,是一款完全免费的压缩解压软件。7-Zip是一款开源的解压缩软件,命令行选项具有强大的设置功能,非常适合用来备份。7-Zip 是一款号称...
  • 世界上压缩比最高的屏幕录像软件Screen2exe(25M/h,含声音,清晰)
  • <br>主要特征: 更新了算法来加大 7z 格式 的压缩比 7-Zip 是基于 GNU LGPL 之下发布的软件 支持格式: 压缩及解压缩:7z、ZIP、GZIP、BZIP2 和 TAR 仅解压缩:RAR、CAB、ISO、ARJ、LZH、CHM...
  • 通常word文档中如果图片较多,就占用较大内存,并且在发送和保存时极不方便,这款软件可以进行最大比例压缩,本人亲测,120M word文档最小可压缩到10M以下,大家有需要可以下载!
  • 将这张图片下载到本地,修改文件后缀为 .rar,然后再解压,你会得到四个文件 这其中有一个「说明.txt」里面是这样写的: 每年,世界各地著名的Warez组织都会推出一个小的动画片来比较,仅仅是用来炫耀其实

    上次写了图片压缩,这倒让我想起几年前看过的一个很有意思的东西

    那就是这张鸭子图:

    不过微信会压缩图片,你可以打开这个链接:http://2.im.guokr.com/F70Kn-4wz7aF5Yejf9W3g6kO4exDBqVEb0TumQmxy5MiAQAAEAEAAEpQ.jpg 来获取原图

    将这张图片下载到本地,修改文件后缀为 .rar,然后再解压,你会得到四个文件

    ▲改后缀名,然后解压

    这其中有一个「说明.txt」里面是这样写的:

    • 每年,世界各地著名的Warez组织都会推出一个小的动画片来比较,仅仅是用来炫耀其实力
    • 要知道,一首普通的MP3,通常就有4000K左右,一张普通的JPG压缩图片也要30-40K,而这个仅有63K的3D动画,你花半个小时也看不完,而且不重复、带音乐!

    双击「prophecy《彗星撞地球》.exe」便能查看这段3D动画

    阿虚简单录了一下前2分钟的效果

    第1段:

    第2段:

    如果感兴趣,可以自己把图片保存下来后看看

    注:系统必须安装有directx8.0才行。按A键可缩小,按S键放大,按F键快速放,按R键重放……

    可能很多人会误以为这是什么逆天的压缩算法,但实际上不是的,这段动画并不是由什么视频压缩而成,背后上实际是靠即时演算而得到的

    就好比给电脑一个谱子,然后电脑其实是在照谱演奏

    另外,像8个关卡的魂斗罗只有128K,32个关卡的超级马里奥甚至只有64K,零几年时红极一时的3D FPS射击游戏 kkrieger(毁灭杀手)仅96KB…

    这些都不是单纯的压缩,背后涉及的原理很多,的确也都很有意思,不过对我们一般人来讲,看了也就图一乐,没有什么实际的用途

    阿虚倒想借由这个问题给大家科普一下——普通的压缩包怎么压缩,才能拥有最好的压缩率?

    ▍1 关于压缩文件的常识

    首先你得知道:压缩率很大程度上取决于你压的是什么东西

    我们一般分5️⃣大文件类型:程序文件,文本文件,压缩图片,压缩音频和压缩视频

    而实际上只有程序文件文本文件这种人类语言的数据是有压缩价值的

    这句话的意思是:图片、音频、视频文件,数据基本上已经压缩了,用压缩软件的压缩算法二次压缩是几乎没有作用的🤷🏻‍♂️

    Kaciras在他的博客也分享过他的测试结果:https://blog.kaciras.com/article/4/WinRAR-vs-7zip-performance

    阿虚自己也实际测试过包括:mobi、epub、docx、pdf、mp3、flac、jpg、png…这些常见格式,压缩率基本都是100%,即原本100MB,压缩后还是100MB

    除外实际有点压缩效果的也就 doxc 和 pdf:100MB 的 docx 大约能压到94MB1GB 的 pdf 能压缩到 986MB

    还有 txt 文件,靠压缩软件还是能有比较不错的压缩率的!

    ▲50M的txt文件的压缩效果

    所以你要是想靠压缩软件来进行压缩视频、音频、图片是几乎没有实际意义的

    对于这种情况,压缩软件基本上就起一个打包作用

    如果准备打包的文件较大,我建议你压缩方式选择「存储」

    这个方式就是几乎直接把文件装在一起,不进行压缩操作,能最大程度的节约在压缩&解压的时间

    如果你是想压缩图片、视频、音频…通常有损压缩才能真正起到效果

    比如降低视频分辨率,降低码率等:https://mp.weixin.qq.com/s/CBhVeL5s9S9ewsgwsdhTsg

    音频的话,一般人用一般设备其实也听不出 flac 和 320K mp3 的区别,但这格式在文件大小上差别就大了:https://mp.weixin.qq.com/s/Am2u6zPd49aWKMjPjbdZ-Q

    如果是图片的话,我前不久才讲过,一般人会用到的压缩方式,也就 png 格式转 jpg 格式了:https://mp.weixin.qq.com/s/pV_WuPXP62QnJ19o76Y2nQ

    ▍2 最好的压缩参数该怎么设置?

    而对于程序文件,压缩还是很有必要的——尤其是你遇到像蓝奏云、闪电盘这类网盘,限制上传大小是100MB的时候

    于是阿虚这几天,就结合自己以往的使用体验&网上的推荐,测试了一下以下4️⃣款软件的压缩效果

    但你需要知道:对于一个 .exe 安装包,压缩是不起效果的(exe实际也属于一种压缩格式了)

    而什么样的程序文件能获得较高的压缩率呢?

    程序中的小文件越多,就越容易获得较高的压缩率,比如下图这种情况

    所以就算你压缩设置啥的完全都一样,也不一定能取得同样的压缩率,具体能压缩多少还是取决与于源文件

    测试之前,先说一下压缩文件的一些参数:

    • 压缩算法: 常见的压缩算法有Defate、Bzip、PPMd、RAR、LZMA、LZMA2,真正决定压缩效果的不是7z、zip、rar等压缩格式,而是压缩算法
    • 字典大小:较大的字典文件能提供较高的压缩比,但同时压缩所需内存会大量增加(解压所需内存也会少量增加),具体大小需根据电脑配置量力而行
    • 单词大小:影响纯文本文件的压缩比,此参数越大,压缩速度越慢,但不影响解压速度
    • 固实压缩:可增加压缩比,如果创建的压缩档案需要更新,建议关闭固实模式
    • CPU线程:线程越高压缩时间越低,但同时压缩所需内存越大

    为了具体说明,我找来一个正好100MB的程序文件,下面看看怎么压缩能压到最低

    我就对这个程序用不同压缩软件,在不同压缩参数下,进行了几十次的压缩测试

    最终的结果便是下面这张图

    ▲点击查看大图

    答案还是显而易见的:

    选用压缩软件7zip,压缩方法LZMA2,字典大小根据自身电脑配置尽可能的大,单词选择273,采用固实压缩,便能取得最高的压缩率

    上图之所以把好压也加亮了,是因为阿虚用的旧版好压很多年了,在正确设置参数的情况下,还是能取得和最新版7zip差不多的压缩率(差0.1M)

    个人觉得,综合好压其他功能的实用性,这款软件还是很值得推荐的

    ● 2.1 字典大小&CPU线程

    测试结论虽然简单粗暴,但还有一些问题需要说明

    首先便是在设置压缩参数的时候,要根据自己的电脑配置量力而行

    选择LZMA2算法,字典大小如果选择1024MB,线程个数还是12的话,一般需要电脑有30G的内存才能完成压缩…

    99%的用户电脑内存都是没这么大的,上面那样设置只会导致压缩失败

    所以你需要适当降低字典大小、降低线程个数!

    ▲可以在右下方自定义压缩配置

    「解压所需内存」一般都是大大低于「压缩所需内存的」

    而且解压所需内存一般最大也就1G左右,如今的电脑基本上都能胜任的

    所以基本上不必担心你的压缩文件别人会因为电脑内存不足而解压不了

    ● 2.2 固实压缩

    然后对于固实压缩还是有必要说明一下的

    压缩参数中的「固实大小」要大于你被压缩文件本身,才能取得最好的压缩率

    假如你有100MB的文件需要压缩,那么固实大小就得设置100MB以上,如128MB

    另外固实压缩虽然具有压缩比高的优点,但也有其缺点

    如果你需要往压缩包里添加文件,或者说想取出压缩包里的某部分文件,对于采用固实压缩的压缩包会较慢

    关于固实压缩更详细的说明,可以到 Bandizip官网的帮助中了解:https://www.bandisoft.com/bandizip/help/what-is-solid-compression

    ▲扫码即可查看

    ● 2.3 PPMd 压缩算法

    还有 PPMd 这种压缩算法,虽然只能单线程,但优势是对纯文字的压缩有加成

    阿虚找来50MB的纯TXT文件,单独对比了PPMd算法和上面得出的最高压缩率设置,的确是PPMd压缩效果更好一点

    ● 2.4 RAR格式

    WinRAR虽然在压缩率上没有优势,但其是唯一带恢复记录功能的压缩软件

    什么是恢复记录?

    假如有个100m的压缩文件,如果不带恢复记录,损坏了1k,那整个这个文件就坏了,如果带有1%的恢复记录,它的大小会变成101m,但在任意位置损坏不超过1m,这个文件就能正常解压!

    所以对于准备长期冷备份的文件,这个恢复记录还是很有作用的(不过,阿虚更建议多重备份来解决这个问题)

    因为WinRAR是商业软件,不开源,需要购买许可证才能使用

    同时由于你懂的原因,这款软件阿虚在公众号也不方便提供,大家要是想使用,可以自己上网找一下注册密钥

    ▍3 压缩软件下载

    于是,如果你对压缩率有要求,我便只推荐你两款压缩软件

    一是好压(旧版):

    ▲好压压缩参数设置页面

    二是7-zip:

    ▲7-zip压缩参数设置页面

    原因是这俩款软件才能对「压缩参数」进行详细设置(Bandizip只能简单设置)

    再主观上来讲,阿虚自己是比较推荐好压(旧版)的

    除了使用符合国人习惯,还提供一些实用的小功能,搭配2345看图王(去广告版),也能方便的查看压缩包内的图片

    旧版好压的下载地址在储物间(axutongxue.com)一直有提供,你也可以关注微信公众号:阿虚同学,在后台回复以下关键词来获取

    解压缩
    

    而7-zip是一款开源软件,在官网即可免费下载:https://sparanoid.com/lab/7z/

    另外不是说不推荐 Bandizip

    这款压缩软件的确好用,但是就算是企业版,也无法对压缩参数进行过多的设置——这是它的缺点

    当然,如果有人想用 Bandizip,阿虚这里也有顺便提供,获取方式还是在后台发送关键词:解压缩

    Bandizip 之前一直有在储物间提供个人版,不过这次更新了企业版,在用这款软件的粉丝可以更新一下

    另外如果你对压缩包密码有疑问,可以去复习我原来写过的这篇文章:https://mp.weixin.qq.com/s/sBxLpr2uwKF2IpTFTrH8HA

    而如果你想搜索压缩包内的内容,则可以复习这篇文章:https://mp.weixin.qq.com/s/ApyutqrsRN8dP65aKzq3mQ

    展开全文
  • Lzw 针对大量的子串多次重复出现的压缩   之前用了一个哈弗曼算法给大家实现了文件的压缩处理,其实上,文件压缩的原理很简单,无非就是把重复出现的元素,用一个特定的方式转化为跟少量的信息来存储。今天我所...

    Lzw 针对大量的子串多次重复出现的压缩 

        之前用了一个哈弗曼算法给大家实现了文件的压缩处理,其实上,文件压缩的原理很简单,无非就是把重复出现的元素,用一个特定的方式转化为跟少量的信息来存储。今天我所给大家分享的就是一个更为引用广泛的压缩算法lzw压缩算法。

    一、lzw的介绍

         LZW压缩算法是一种新颖的压缩方法,由Lemple-Ziv-Welch 三人共同创造,用他们的名字命名。它采用了一种先进的串表压缩,将每个第一次出现的串放在一个串表中,用一个数字来表示串,压缩文件只存贮数字,则不存贮串,从而使图象文件的压缩效率得到较大的提高。奇妙的是,不管是在压缩还是在解压缩的过程中都能正确的建立这个串表,压缩或解压缩完成后,这个串表又被丢弃。

     

    简单的说明一下:

    Ababcabab这个字符串,开起来9个字符组成的,但是会发现一点就是ab这个字符组合比较的多。如果我们用一个数字,也就是7来表示ab的话,则字符串就变为了77c77,这样一来字符串的字符个数就变为了5个,如果大家仔细些会发现,如果我们用一个数字8来表示abab,则原来的字符串就变为了8c8只有3个字符了,是不是很神奇哈。

    从这个例子我们就可以看出LZW算法的适用范围是原始数据串最好是有大量的子串多次重复出现,重复的越多,压缩效果越好。反之则越差,可能真的不减反增了。

    比如:

    一个如此重复的文件:



    大小为:

     


     

    压缩后效果就非常的显著:

     

     

    文件大小变为原来的1/30

     

     具体思想:

    比如我们大家所熟知的ASCII码,这个码表是与我们常见的字符是一一对应的,比如我们说‘a,我们也可以写成97,这两者就是等价的。其实上这就是一个码表。所以人们就想到,我们可不可以用以一个码表示一个或者多个的字符,比如8表示ab这两字符,我们就能将abcab这种的字符串缩小为8c8了。 但是我们知道字节只有0~255,如果我们要扩展的话就必须增加自己的定义。既,我假设我用增加了256~65534这么一段表示新的码表。

     

    具体步骤:

    ①打开一个待压缩文件与存放压缩后的文件

    ②读入一个字节作为后缀,判断这个词字典中是否存在,存在则直接输出,不存在则加入字典中。

    ③如果超过了最大的长度则,将当前码表写出到文件中,清空,再次读入

    最后,将没有写完的信息,和码表都输出,压缩就完成了

     

    举一个例子说明:

    先说两个概念

    前缀prefix:一个词组的前面一个字符 ,比如 ab,前缀为a8f前缀为8

    后最suffix:反之,为后一个字符,比如 ab,后缀为b8f后缀为f

    有了前缀后缀,我们就能清楚的表示出来一个词了。

     

    同样,我们还来做一个字符串 ababbacb  8个字符 

     

    第几步

    前缀

    后缀

    存在对应码

    输出

    1

     

    a

    (,a)

     

     

     

    2

    a

    b

    (a,b)

    no

    a

    256

    3

    b

    a

    (b,a)

    no

    b

    257

    4

    a

    b

    (a,b)

    yes

     

     

    5

    256

    b

    (256,b)

    no

    256

    258

    6

    b

    a

    (b,a)

    yes

     

     

    7

    257

    c

    (257,c)

    no

    257

    259

    8

    c

    b

    (c,b)

    no

    c

    260

     

    把输出来的和最后一个后缀连在一起则是:

      a,b,256,257,c,b        

    6个字符,那么就达到了压缩的目的。

    对应生成的码表则是:

     

    256

    257

    258

    259

    260

    a,b

    (b,a)

    (256,b)

    (257,c)

    (c,b)

     

    解压缩就很简单了,将输出字符串按照码表对应转化回来就实现了。

      a,b,256(ab,257(ba),c,b

    即 ababbacb

    压缩成功。

     

     

    当然我们不能一直无穷之境的增加码表的长度,再说内存也容不下这么长的码表。正如我之前所说的,我用了0~65534保存字节所对应的编码,0~255是系统字节的长度,256~65534是我自己定义的。如果超过了65534的话,我们这必须再次编码。即将原来所对应的编码输出,将256~65534这一段清空,再次编码就可以了。

    为了记录我们是在哪里清空的,所有又在文件中写一个字符,表示 “清除”,我的程序中用的是65535表示。

      

    详细代码设计

     

     

     

    压缩过程

    ①打开一个待压缩文件与存放压缩后的文件

    	//打开被压缩文件
    			java.io.FileInputStream fis = new java.io.FileInputStream(path);
    			//压缩文件输出流
    			java.io.FileOutputStream fos = new java.io.FileOutputStream(path+".stzip");
    			java.io.DataOutputStream dos = new java.io.DataOutputStream(fos);

      

    ②读入一个字节作为后缀,判断这个词字典中是否存在,存在则直接输出,不存在则加入字典中。

    prefix=fis.read();//读入一个字节
    while(fis.available()>0){
    suffix=fis.read();//读入一个后缀
    			    index=lz.getIndex(prefix, suffix);//得到对应的下标
    				if(index!=-1){//存在元素在表里面
    					prefix=index;//前序变为标号
    				}else{//在表里不存在
    				//	System.out.println("输出了~"+prefix);
    					dos.writeChar(prefix);//输出前缀
    					lz.add(prefix,suffix);//加入到表中
    					prefix=suffix;//前缀变为后缀
    
    				}
    }

     

     

    ③如果超过了最大的长度则,将当前码表写出到文件中,清空,再次读入

     

     

    	if(lz.length==lzw.Max_Length){//超过最大长度则,重置
    					dos.writeChar(65535);//写出一个65535作为重置的标示 与码表的打印
    					//写出码表
    			//		dos.writeInt(lz.length);//码表长度
    					System.out.println("写出长度~"+lz.length);
    					for(int i=256;i<lz.length;i++){
    						dos.writeChar(lz.node[i].prefix);//前缀写出
    						dos.writeChar(lz.node[i].suffix);//后缀写出
    					}
    					
    					lz = new lzw();//清空原来信息
    				}

     

    ④最后,将没有写完的信息,和码表都输出,压缩就完成了

    dos.writeChar(prefix);//输出最后一个没有配对的
    			
    			//输出最后的的码表
    		//	System.out.println("写出标记~"+65535);
    			dos.writeChar(65535);//写出一个-1作为重置的标示 与码表的打印
    			//写出码表
    			dos.writeInt(lz.length-256);//码表长度
    			//System.out.println("写出长度~"+(lz.length-256));
    			for(int i=256;i<lz.length;i++){
    				//System.out.println("写出前后缀~"+lz.node[i].prefix+","+lz.node[i].suffix);
    				dos.writeChar(lz.node[i].prefix);//前缀写出
    				dos.writeChar(lz.node[i].suffix);//后缀写出
    			}

     

    解压缩过程:

    ①读入码表之前的压缩信息

    char data;
    				int current=0;
    				char []codeData = new char[65536];
    				lzw lz = new lzw();//自定义码表
    				
    				data=dis.readChar();
    				//System.out.println("读取字符~"+data);
    				while(data!=65535){//把码表钱的东西读取出来
    				//	System.out.println("开打文件中有的内容"+current+"是"+data);
    					codeData[current]=data;
    					current++;//当前位置增加
    					data=dis.readChar();
    				}

     

    ②读入对应长度的码表

    int length = dis.readInt();//得到码表的长度
    				//System.out.println("独到的长度"+length);
    				for(int i=0;i<length;i++){//读入码表
    					int prefix = dis.readChar();
    					int suffix = dis.readChar();
    					//System.out.println("第"+i+"个的数据"+prefix+","+suffix);
    					
    					lz.add(prefix, suffix);
    				}

     

    ③翻译编码,写出源文件

    //解压缩、写出该部分的源文件
    				for(int i=0;i<current;i++){
    					//System.out.println("传进来的数据是~"+codeData[i]);
    					lz.writeIt(dos, codeData[i]);
    
    
    	public void writeIt(java.io.DataOutputStream dos,int index){
    	//	System.out.println("进来的index是"+index);
    		if(index>255){//是生成的码则需要转化为byte输出
    			writeIt(dos,node[index].prefix);
    			writeIt(dos,node[index].suffix);
    		}else{
    			try {
    		//		System.out.println("解压输出了~"+index);
    				//char data=(char) index;
    				dos.write((char)index);
    				//dos.writeChar(data);
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    	}

     

    比较,lzw和哈弗曼做比较,lzw的代码更为简便,实现更为简单,效率也比哈弗曼高。但是LZW得算法比较难以理解。

    <!--EndFragment--><!--EndFragment--><!--EndFragment--><!--EndFragment-->
    • 大小: 34.1 KB
    • 大小: 34.1 KB
    • 大小: 35.2 KB
    • 大小: 95.8 KB
    展开全文
  • 史上超高压缩软件2009

    2009-09-04 14:46:16
    的模式0,它的压缩率UHARC的最高压缩率还高(速度约是UHARC的1/3~1/4).压缩时以内存 大小决定,千万不要在内存不足的情况下使用较高的模式压缩或解压,否则会出现内存不足 的错误或者速度会大大降低以至无法忍受. 2...
  • 压缩软件

    2020-06-20 15:53:52
    压缩软件 一、实验目的和要求 利用哈夫曼树编码写出一个解压缩软件 二、实验环境 DEVC++ qt 三、实验内容 (1)压缩对象为外存任意格式任意位置的文件。 (2)运行时,压缩原文件的规模应不小于5K。运行后,外存上...

    解压缩软件

    一、实验目的和要求

    利用哈夫曼树编码写出一个解压缩软件

    二、实验环境

    DEVC++ qt

    三、实验内容

    (1)压缩对象为外存任意格式任意位置的文件。
    (2)运行时,压缩原文件的规模应不小于5K。运行后,外存上保留压缩后的文件。
    (3)提供解压文件与原文件的相同性对比功能。
    (4)建议,形成带交互界面功能的系统。

    四、实验过程

    4.1 任务定义和问题分析

    ①建立哈夫曼树
    ②利用文件流进行文件操作
    ③设计交互界面

    4.2 数据结构的选择和概要设计

    哈夫曼树

    4.3 详细设计

    4.3.1创建一个哈夫曼树结点

    建立一个哈夫曼树的结点,要在结点中我们设定一个权值key,左孩子,右孩子,父节点,这个父节点方便在之后进行树的创建。

    struct node
    {
    int key;
    int lkid,rkid,parent;
    };

    4.3.2 建立所需函数

    寻找权值最小的两个数
    统计字符出现的频率
    创建哈夫曼树的函数
    创建哈夫曼编码的函数
    解压函数
    压缩函数

    4.3.3 创建哈夫曼树
    ①哈夫曼树的创建过程需要一个排序的过程,每次找出权值最小的两个结点。先在没有被建立成树的结点中标记一个m1和m2,再遍历找比m1小的,找到以后将这个结点标记为m1,再找第二小的,标记为m2,从而找到最小的两个结点。
    ②哈夫曼树权值的大小也就是他出现的频率,利用上面的排序,找出最小的两个结点m1和m2,将他们组成一个家庭,将他们的权值之和赋值给父节点。
    ③对这个结点进行哈夫曼编码,左0右1。我们设定一个标记p,如果结点p的父亲的左孩子是p的话,给p这个节点的哈夫曼编码加0,他父节点的右孩子是p的话,就给他的哈夫曼编码加1。最后将这个标记p标为p的父节点。

    4.3.4 统计从文件读出的字符串总共有多少种字符,同时统计这些字符的频率
    我们用字符的ascii码作为频率数组的下标,从文件中读出的字符串为str,一个一个遍历str,如果一个字符出现一次,给它对应的ascii作为下标的频率数组加一。最后再遍历一次,如果f [i]!=0,证明有字符串,给总数n加一,作为统计的字符串总数,也就是哈夫曼树的结点数。

    4.3.5 将哈夫曼码转为等长二进制码
    我们压缩的想法是,将哈夫曼码每八位做为一个单位,这八位二进制码的十进制对应的ascii码又对应一个字符,最后将所有的字符放在一起,写入压缩文件,达到压缩的效果。这个函数让每一种字符对应的ascii码都有对应的等长二进制码,方便后面压缩。每八位作为一个单位,不足八位的用0补齐。

    4.3.6 压缩函数
    ①首先打开文件,同时获取文件名。将文件名截取为名字部分,和文件格式部分,方便之后压缩和解压命名文件名。
    ②用二进制打开文件后,用

           f1.seekg(0,ios::end);
           int l=f1.tellg();
    

    来获取文件大小,之后创建一个字符串s来存放文件读出的字符串。
    ③统计字符串中的总字符种类,频率。再利用函数创建哈夫曼树,哈夫曼编码。再创建一个数组w用来放各个字符的频率。这个时候w的下标就是之前各个字符的ASCII码。
    ④创建一个string code,用来将所有的哈夫曼编码连起来,之前adr [256]的值,这样利用adr [256]我们就能找到hufcode的值,因为code的下标就是adr[256]。连起来就是,只要知道字符,就能知道他对应的哈夫曼编码。
    ⑤现在我们就得到了哈夫曼的编码,然后继续按每八位一个单位,不足8位的用0补齐。
    ⑥再创建一个新字符串 ns来储存新的压缩的字符串,将上面的code每八位处理一次,每八位的字符串赋值给s,s 经过ezs()函数,也就是二转十进制,得到一个数字,最后将这个数字根基ascii码转换为字符,再将这个字符赋值给ns,再一次处理后面的code,就得到了新压缩后的字符。
    ⑦之后我们还要把这个文件的类型,大小,每个字符的权值等信息写进去,方便后面解压。在设定一个结束的符号,最后加上之前的ns。
    ⑧打开一个新文件,将ns读进去。
    ⑨再读取这个文件的大小,计算压缩率。

    4.3.7 解压函数
    ①同样的方法打开文件,获取字符串s,处理文件名。
    注:这里有个函数,因为在之前的压缩函数中,我们将文件类型,字符的权值也写进去,因此我们要通过一个函数来截取这些信息。这些信息在之前设立的结束标识符之前。遍历到这个标识符结束就行。再按照文件大小,类型,字符,字符,频率截取就行。这样才能进行后面的解压操作。
    ②遍历s,获取每个字符的ascii码,再获取每个字符对应的等长二进制码。
    ③继续通过频率f []!=0,来获取哈夫曼树的结点数。
    ④创建哈夫曼数,写哈夫曼编码。这里的哈夫曼编码相当与一个查询表。
    ⑤获取哈夫曼树权值最大的结点,他的哈夫曼编码是最短的,后面读到的哈夫曼编码只要不小于这个长度,再来遍历是否有对应的字符。因此要不断遍历读取由文件中字符串转化为的二进制码,一个一个寻找哈夫曼编码对应的字符。如果找到一个和哈夫曼编码相同的哈夫曼码,这个哈夫曼的下标就是这个字符的ascii码,就知道了他的字符,将这个字符加入ns。
    ⑥这个ns的长度也就是源文件的长度。将之前获得的文件名,文件类型读出,创建文件。

    五、测试及结果分析

    5.1 实验数据

    ①word文件
    在这里插入图片描述
    ②png文件
    在这里插入图片描述

    ③ppt文件
    在这里插入图片描述

    5.2 结果及分析

    ①word文件
    在这里插入图片描述
    在这里插入图片描述

    ②png文件
    在这里插入图片描述

    在这里插入图片描述

    ③ppt文件
    在这里插入图片描述
    在这里插入图片描述
    ④解压ppt文件
    在这里插入图片描述
    在这里插入图片描述

    六、实验收获

    在这里插入图片描述
    从这个代码中可以看出,有的问价压缩率比较客观,但有的文件压缩效果不是很好,比如图片文件格式,有可能会比以前的文件稍大一点,但对于大一点的文件来说效果就好很多。具体原因可能是在压缩的时候写入了字符频率,文件大小的原因,导致本来就很小的文件,在压缩空间很小的条件下,有写入了部分信息,导致文件变大。
    在这里插入图片描述
    经测试,发现图片类(JPG文件)的文件压缩率都不高,几乎都为0。咨询过同学后发现他们也有这种问题。这种越压缩越大可能是哈夫曼树压缩的弊端,对于部分类型的文件压缩效果一般。如果用其他算法压缩文件或许可以解决这个问题。

    #include<iostream>
    #include<string>
    #include<fstream>
    #include<math.h>
    
    using namespace std;
    
    struct element
    {
        int weight;
        int lkid,rkid,parent;
    };
    void huffman_tree(element* hufftree,int* w,int n);//构造叶子节点长为n的哈夫曼树
    void sort(element* hufftree,int &a,int &b,int n);//找出权值最小的两个节点
    void huffman_code(element* hufftree,int n,string* code);//对哈夫曼树进行编码
    void tongji(char* str,int len,int &n);//对文件的二进制串的数量进行统计 返回含有各个字符频率的数组
    string dcr(int n);//根据index生成等长二进制编码
    void compress();//压缩函数
    void decompress();//解压函数
    int ezs(string code);//二进制码转十进制
    string i_to_s(int l);
    int s_to_i(string str);
    int getprefix(char *str,int l,string &type,int &len);//返回去除了前缀的新下标
    string getstr(char* str,int begin,int l);
    int dictionaries[256];//dictionaries对应的是hufftree的下标 知hufftree下标可知哈夫曼编码code[dictionaries[index]]
    int freq[256];
    string equal_length_code[256];//等长的二进制编码
    
    int main()
    {
        string choose;
    	
    	while(true)
    	{
    		cout<<"输入1压缩文件 输入2解压文件 输入其它退出"<<endl;
    		cin>>choose;
    		if(choose=="1")
    			compress();
    		else if(choose=="2")
    			decompress();
    		else
    			break;
    		cout<<"OK!"<<endl;
    	}
        return 0;
    }
    
    void sort(element* hufftree,int &a,int &b,int n)
    {
        int t1,t2;
        for(int i=0;i<2*n-1;i++)
        {
            if(hufftree[i].parent==-1)
            {
                t1=i;
                a=i;
                break;
            }
        }
        for(int i=0;i<2*n-1;i++)
        {
            if(hufftree[i].parent==-1&&i!=a)
            {
                t2=i;
                b=i;
                break;
            }
        }
        for(int i=0;i<2*n-1;i++)
        {
            if(hufftree[i].parent==-1&&i!=a&&(i<n||hufftree[i].lkid!=-1))//比较所有有权值的节点
                if(hufftree[i].weight<hufftree[a].weight)
                    a=i;
        }
        if(a==b)
            b=t1;
        for(int i=0;i<2*n-1;i++)
        {
            if(hufftree[i].parent==-1&&i!=a&&i!=b&&(i<n||hufftree[i].lkid!=-1))
                if(hufftree[i].weight<hufftree[b].weight)
                    b=i;
        }
    }
    
    void huffman_tree(element* hufftree,int* w,int n)
    {
        for(int i=0;i<2*n-1;i++)
        {
            hufftree[i].parent=-1;
            hufftree[i].lkid=-1;
            hufftree[i].rkid=-1;
        }
        for(int i=0;i<n;i++)
            hufftree[i].weight=w[i];
        for(int i=n;i<2*n-1;i++)
        {
            int a,b;
            sort(hufftree,a,b,n);
            hufftree[a].parent=i;
            hufftree[b].parent=i;
            hufftree[i].lkid=a;//左最小
            hufftree[i].rkid=b;
            hufftree[i].weight=hufftree[a].weight+hufftree[b].weight;
        }
    }
    
    void huffman_code(element* hufftree,int n,string code[256])
    {
        for(int i=0;i<n;i++)
        {
            int p=i;
            while(p!=2*n-2)
            {
                if(hufftree[hufftree[p].parent].lkid==p)
                    code[i]='0'+code[i];
                else
                    code[i]='1'+code[i];
                p=hufftree[p].parent;
            }
        }
    }
    
    void tongji(char* str,int len,int &n)
    {
        n=0;
    
        for(int i=0;i<len;i++)//ascii范围是-128-127
        {
            int ascii=str[i];
            if(ascii>=0)
                freq[ascii]++;
            else
            {
                ascii=ascii*-1+127;
                freq[ascii]++;
            }
        }
        for(int index=0;index<256;index++)//index范围是0-255 经常需要转换
            if(freq[index]!=0)
                n++;
    }
    
    string dcr(int n)
    {
        int a[8];
        int i=0;
        string str="";
        while(n!=0)
        {
            a[i]=n%2;
            n/=2;
            i++;
        }
    
        for(n=i-1;n>=0;n--)
        {
            if(a[n]==1)
            	str+='1';
            else
            	str+='0';
    	}
        int l=str.length();
    	if(l<8)
            for(int k=0;k<8-l;k++)
    			str='0'+str;
        return str;
    }
    
    void compress()
    {
        string filename;
        cout<<"输入要压缩的文件的完整路径"<<endl;
        cin>>filename;
        int fl=filename.length();
        for(int i=0;i<fl;i++)
        	if(filename[i]=='\\')
        	{
        		filename.insert(i,"\\\\");
        		i+=2;
    		}
    	for(int i=0;i<256;i++)
            equal_length_code[i]=dcr(i);
    
        for(int i=0;i<256;i++)
            freq[i]=0;
    
        for(int i=0;i<256;i++)
            dictionaries[i]=-1;
    
        string name;
        string type;
        for(int i=filename.length()-1;i>=0;i--)
            if(filename[i]=='.')
            {
                name=filename.substr(0,i);
                //cout<<name<<endl;
                type=filename.substr(i+1);
                //cout<<type<<endl;
                break;
            }
        int n;
        ifstream f1;
        char* fn=(char*)filename.data();
        f1.open(fn,ifstream::binary);
        f1.seekg(0,ios::end);
        int l=f1.tellg();
        f1.seekg(0,ios::beg);
        char* str=new char[l];
        f1.read(str,l);
    
    
        f1.close();
        tongji(str,l,n);
     
    	
        element* hufftree=new element[2*n-1];//哈夫曼树共有2n-1个节点
        string h_code[n];//ascii码对应的权值code[dictionaries[index]] index范围为0-255 0-127是正常的 128-255另作转换
        int* w=new int[n];
    
        int k=0;
        for(int i=0;i<256;i++)//将零散分布的freq放入到整齐的w[k]
            if(freq[i]!=0)
            {
                w[k]=freq[i];//w是权
                dictionaries[i]=k;
                k++;
            }
    
        huffman_tree(hufftree,w,n);//构建哈夫曼树
        /*for(int i=0;i<2*n-1;i++)
            cout<<hufftree[i].weight<<endl;*/
    
        huffman_code(hufftree,n,h_code);//根据哈夫曼树生成每个字符对应的哈夫曼编码
        /*for(int i=0;i<n;i++)
            cout<<h_code[i]<<endl;*/
    	
    	if(n==1)
    		h_code[0]='0';
    	
        //cout<<l<<endl;
        string code="";
        for(int i=0;i<l;i++)
        {
            int ascii=str[i];
            if(ascii>=0)
                code+=h_code[dictionaries[ascii]];
            else
                code+=h_code[dictionaries[ascii*-1+127]];
        }
        //cout<<"step2\n";
        int len=code.length();
        //cout<<len<<endl;
        //cout<<len;
        if(len%8!=0)//不够八位的补上0
        {
            int complement=8-l%8;
            for(int i=0;i<complement;i++)
                code+='0';
        }
        //cout<<"step3\n";
        string newstr="";//压缩后的新字符串
        for(int i=0;i*8<len;i++)
        {
            string s="";
            for(int j=0;j<8;j++)//获得八位二进制码
                s+=code[i*8+j];
            int index=ezs(s);//转化为十进制 八位二进制生成一个字节
            //cout<<index;
            if(index<128)
                newstr+=char(index);
            else
                newstr+=char((index-127)*-1);
        }
        string prefix;
        prefix+=type+'|';
        prefix+=i_to_s(l);//前缀 解压时用
        for(int i=0;i<256;i++)
        {
            if(freq[i]!=0)
            {
                prefix+='|';//字符前后用||分隔
                if(i<128)
                    prefix+=char(i);
                else
    				prefix+=char((i-127)*-1);
                prefix+=i_to_s(freq[i]);
            }
        }
        prefix+='|';
        prefix+="stop";
        newstr=prefix+newstr;
    
        //cout<<prefix<<"\n";
        l=newstr.length();
        //cout<<endl;
        //cout<<l;
    
        string lmyfile=name+".yasuo";
        char* lf=(char*)lmyfile.data();
    
        ofstream f2;
        f2.open(lf,ofstream::binary);
        const char* a=newstr.data();
        f2.write(a,l);
        f2.close();
    
    
        delete[] hufftree;
        delete[] w;
    
        delete[] str;
    }
    
    void decompress()
    {
    	string filename;
    	cout<<"输入要解压文件的完整路径"<<endl;
    	cin>>filename;
    	int fl=filename.length();
    	for(int i=0;i<fl;i++)
        	if(filename[i]=='\\')
        	{
        		filename.insert(i,"\\\\");
        		i+=2;
    		}
    	
    	for(int i=0;i<256;i++)
            equal_length_code[i]=dcr(i);
    
        for(int i=0;i<256;i++)
            freq[i]=0;
    
        for(int i=0;i<256;i++)
            dictionaries[i]=-1;
    
    	string hc[256];
    	
        string name;
        string type;
        for(int i=filename.length()-1;i>=0;i--)
        {
            if(filename[i]=='.')
            {
                name=filename.substr(0,i);
                break;
            }
        }
        //cout<<name<<endl;
    
        ifstream f1;
        char* fn=(char*)filename.data();
        f1.open(fn,ifstream::binary);
        f1.seekg(0,ios::end);
        int l=f1.tellg();
        f1.seekg(0,ios::beg);
        char* str=new char[l];
        f1.read(str,l);
        f1.close();
    
    	int len;//字符的总数
    
        int begin=getprefix(str,l,type,len);//begin是新的下标
    
        string code="";
        for(int i=begin;i<l;i++)
        {
            int ascii=str[i];
            if(ascii>=0)
                code+=equal_length_code[ascii];
            else
                code+=equal_length_code[ascii*-1+127];
        }
    
        //cout<<code.length();
        int n=0;//原哈夫曼树叶子节点个数
        for(int i=0;i<256;i++)
            if(freq[i]!=0)
                n++;
    
        element* hufftree=new element[2*n-1];//哈夫曼树共有2n-1个节点
        string h_code[n];//index范围为0-255 0-127是正常的 128-255另作转换
        int* w=new int[n];
    
        int k=0;
        for(int i=0;i<256;i++)//将零散分布的freq放入到整齐的w[k]
            if(freq[i]!=0)
            {
                w[k]=freq[i];//w是权
                dictionaries[i]=k;
                k++;
            }
    
        huffman_tree(hufftree,w,n);//构建哈夫曼树
        /*for(int i=0;i<2*n-1;i++)
            cout<<hufftree[i].weight<<endl;*/
    
        huffman_code(hufftree,n,h_code);//根据哈夫曼树生成每个字符对应的哈夫曼编码
        /*for(int i=0;i<n;i++)
            cout<<h_code[i]<<endl;*/
        
        if(n==1)
    		h_code[0]='0';
        
        for(int i=0;i<256;i++)
        	if(freq[i]!=0)
        		hc[i]=h_code[dictionaries[i]];
    	
    	int cl=code.length();
        string newstr="";
        int a=0;//遍历数组code的下标
    
        int max=0;//设max是出现频率最高的字符的下标
        for(int i=1;i<256;i++)
            if(freq[i]>freq[max])
                max=i;
        int min_length=h_code[dictionaries[max]].length();
        //cout<<min_length;
        for(int k=0;k<len;k++)//len原文件的字符数
        {
            string temp="";//不断读取code中的二进制码 找到哈夫曼编码
            while(a<cl)
            {
                bool found=false;
                temp+=code[a];
                if(temp.length()<min_length)
                {
                    a++;
                    continue;
                }
                
                for(int index=0;index<256;index++)
                {
                	if(temp==hc[index])
                	{
                		found=true;
    					if(index<128)
                			newstr+=char(index);
                		else
                			newstr+=char((index-127)*-1);
                		break;
    				}
    			}
                a++;
                if(found==true)
                    break;
            }
        }
        l=newstr.length();//原文件长度
        const char* b=newstr.data();
    
    
        string lmyfile=name+'.'+type;
        char* lf=(char*)lmyfile.data();
        ofstream f2;
        f2.open(lf,ofstream::binary);
        f2.write(b,l);
        f2.close();
    
        delete[] str;
        delete[] w;
        delete[] hufftree; 
    }
    
    int ezs(string code)
    {
        int l=code.length();
        int result=0;
        for(int i=0;i<l;i++)
            if(code[i]=='1')
                result+=pow(2,l-i-1);
        return result;
    }
    
    string i_to_s(int l)
    {
        string str="";
        while(l>=10)
        {
            str=char(l%10+48)+str;
            l/=10;
        }
        str=char(l+48)+str;
        return str;
    }
    
    int s_to_i(string str)
    {
        int n=0;
        for(int i=0;i<str.length();i++)
            n=n*10+int(str[i]-48);
        return n;
    }
    
    int getprefix(char *str,int l,string &type,int &len)
    {
        string newstr;
        //cout<<l<<endl;
        int e=0;//结束标志stop开始的地方
        for(int i=0;i<l;i++)
            if(str[i]=='s'&&str[i+1]=='t'&&str[i+2]=='o'&&str[i+3]=='p')
                e=i;
        //cout<<str[e]<<str[e+1]<<str[e+2]<<str[e+3];
        int i=0;
        int front,rear;
        for(i;i<e;i++)
            if(str[i]=='|')
            {
                rear=i;
                type=getstr(str,0,rear);
                i++;
                break;
            }
        //cout<<type;
        front=rear+1;
        for(i;i<e;i++)
            if(str[i]=='|')
            {
                rear=i;
                len=s_to_i(getstr(str,front,rear-front));
                break;
            }
        //cout<<len;
    
        //cout<<str[i+1];
        while(i<e)
        {
        	if(str[i]=='|')
        	{
        		int w;
                i++;
                if(i>=e)
                	break;
                int ascii=str[i];
    
                i++;
                front=i;
                for(i;i<e;i++)
                {
                    if(str[i]=='|')
                    {
                        rear=i;
                        w=s_to_i(getstr(str,front,rear-front));
                        break;
                    }
                }
                if(ascii>=0)
                    freq[ascii]=w;
                else
                    freq[ascii*-1+127]=w;
    		}
    	}
    	return e+4;
    }
    
    string getstr(char* str,int begin,int l)
    {
        string s="";
        for(int i=begin;i<begin+l;i++)
            s+=str[i];
        return s;
    }
    
    展开全文
  • 7-Zip是一款号称有着现今最高压缩比的压缩软件,它不仅支持独有的7z文件格式,而且还支持各种其它压缩文件格式,其中包括Zip、RAR、CAB、GZip、BZip2和TAR等等。此软件压缩的压缩比要比普通Zip文件高30-50% ,因此,...
  • 7-zip是一款号称有着现今最高压缩比的压缩软件,它不仅支持独有的7z文件格式,而且还支持各种其它压缩文件格式,其中包括zip, rar, cab, gzip, bzip2和tar。此软件压缩的压缩比要比普通zip文件高30-50%。因此,它...
  • Zip 是一款号称有着现今最高压缩比的压缩软件,它不仅支持独有的 7z 文件格式,而且还支持各种其它压缩文件格式,其中包括 ZIP, RAR, CAB, GZIP, BZIP2和 TAR 等等。此软件压缩的压缩比要比普通 ZIP 文件高 30-50% ...
  • 最高压缩比 强大的 AES-256 加密 可更改和配置压缩的算法 支持超大文件(最大支持到16EB) Unicode文件名支持 支持固实压缩,容许内类的档案在用一个串流中压缩,使类似的内容被有效的压缩 支持档案的文件头...
  • 首先在这里先介绍一下7z压缩软件,7z是一种主流的 压缩格式,它拥有极高的压缩比。在计算机科学中,7z是一种可以使用多种压缩算法进行数据压缩的档案格式。主要有以下特点: 来源且模块化的组件结构 最高压缩比 ...
  • 注:以下数据均采用“最好”压缩得出。...文件格式压缩前大小(字节)rar压缩后大小(字节)zip压缩后大小(字节)rar压缩率zip压缩率JPEG25,049,66624,379,71024,379,3922.67%2.68%BMP22,616,5508,...
  • 几款强力压缩打包软件

    万次阅读 2015-12-15 22:19:52
    1、 7-Zip是软件盒子极力推荐的免费开源的拥有极高压缩比压缩软件!无论是你是个人还是用于商业,您都可以在任何电脑上使用它,并不需要对 7-Zip 付钱!7-zip使用了 LZMA 与 LZMA2 算法的 7z 格式 拥有比...
  • 19种音频格式介绍及音质压缩比的比较     目录 前言..........................................................................................................................................2  1. ...
  • 说到压缩解压软件是目前电脑和手机必不可少的的软件,无论你是从网上下载的文件,还是好基友分享给你的文件,基本上都会见到压缩包。雷锋哥从接触电脑至今,真正在用的就只有三款压缩软件,分别是WinZip、WinRAR、7-...
  • rar压缩软件.rar

    2016-02-13 10:52:44
    例如,这个命令将从当前目录中所有的 RAR 压缩文件中解压的 *.asm 文件: rar e '*.rar' '*.asm' 命令可以是下列中的任何一个: a 添加文件到压缩文件中。 例子: 1) 从当前目录添加所有的 *.hlp 文件到 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 34,240
精华内容 13,696
关键字:

压缩比最高的压缩软件