压缩——很大的文件为什么能够被压缩成小文件

本文为压缩相关内容部分内容:https://alvincr.com/2021/01/compress-entropy/

(数据压缩测试、字典、固实压缩、熵及其作用)

一:压缩原理

1 压缩前提

首先需要明白压缩这个技术为什么能存在,首先先联想一下我们生活中的压缩,能够压缩的东西必须要有空隙,例如海绵中有大量的空气,因此才能把它压扁,而铁锭中就没有空气,很难再进行压缩。

计算机中的压缩亦是如此,但在压缩文件中,需要的不是空气,而是重复的内容。2^16=65536,理论上一个字就有这么多种表示方法,但是并不是每个字出现的概率都相同,有些字出现的概率就会高很多,同样使用这个字组成的词的概率 并不相同,而是某个特定的词使用次数更多,这就是文件中的“空气”。

一篇小说中会多次出现主角的名字,如果这个主角叫alvincr,那么我就可以用x来表示alvincr,在压缩的过程中遇到alvincr就替换成x,这样就能节省很多字母,解压的时候遇到x就变成alvincr,那么文件就又回来了。

假如有一个文件是写了一千遍的alvincr,

那么压缩的时候既可以直接用x替换alvincr,然后再统计x的数量为1000,最终输出的结果很可能就是这样的:x-?1000(假设这里-表示转义符,-?用于表示重复的次数)

如果我将alvincr重复无穷次,那么最后压缩的效率甚至能达到:1000000:1(个人随意写的数字,并没有做具体实验)

使用记事本打开效果:

2 压缩

压缩后的文件会变成:规则表+内容+附录 的形式,当我们进行解压的时候需要去查找解压的规则,即查找究竟X代表的是什么,是alvincr.com?还是alvincr?

压缩分为无损压缩和有损压缩,对于准确性要求不高的文件可采用有损压缩的形式,例如打电话时及时损失了一些原有的细节,也不会影响通话的质量;但是对于我写的文章,如果压缩软件进行有损压缩,你可能就完全看不出来我原来写的什么了。

3 字典

通过将文本中比较长且出现次数较多的文字,替换成特定的ASCII码,例如将alvincr.com替换成01,01就是alvincr.com的字典,因此如果文本是:本文来自alvincr.com,那么压缩后就会变成:本文来自01,这样就能大幅度减少文字的长度。

虽然字典设置的越大,压缩后的文件越小,但是压缩速度会变慢,资源消耗变大。从上图可以看出rar默认使用4MB的字典,rar5使用32MB字典。

字典设置的越大,那么能够处理的内容就越多,当字典空间耗尽后将会重新启动一个新字典,在运行字典的时候,整个字典全都保存在内存中,因此如果内存容量较小的用户,还是不要将字典设置那么大,经过下文测试(压缩选项-部分)发现rar的32MB字典完全能够实现压缩的效果。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中可以使用ZipInputStream和GZIPInputStream来解压缩压缩文件,其中ZipInputStream可以处理嵌套的压缩文件。 以下是一个用Java解压缩嵌套的压缩文件的示例代码: ```java import java.io.*; import java.util.zip.*; public class UnzipExample { public static void unzip(File zipFile, File destination) throws IOException { byte[] buffer = new byte[1024]; try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) { ZipEntry zipEntry = zis.getNextEntry(); while (zipEntry != null) { File newFile = newFile(destination, zipEntry); if (zipEntry.isDirectory()) { if (!newFile.isDirectory() && !newFile.mkdirs()) { throw new IOException("Failed to create directory " + newFile); } } else { File parent = newFile.getParentFile(); if (!parent.isDirectory() && !parent.mkdirs()) { throw new IOException("Failed to create directory " + parent); } try (FileOutputStream fos = new FileOutputStream(newFile)) { int len; while ((len = zis.read(buffer)) > 0) { fos.write(buffer, 0, len); } } } zipEntry = zis.getNextEntry(); } } } private static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException { File destFile = new File(destinationDir, zipEntry.getName()); String destDirPath = destinationDir.getCanonicalPath(); String destFilePath = destFile.getCanonicalPath(); if (!destFilePath.startsWith(destDirPath + File.separator)) { throw new IOException("Entry is outside of the target directory: " + zipEntry.getName()); } return destFile; } public static void main(String[] args) throws IOException { File zipFile = new File("example.zip"); File destination = new File("unzipped"); unzip(zipFile, destination); } } ``` 该示例代码使用了try-with-resources语句来确保关闭流,它还包含了一个newFile()方法,该方法用于检查解压缩文件的目录是否在指定的目标目录中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值