五:亲自尝试压缩数据

0 开篇

(1)文件储存的基本单位是什么?

字节(1字节=8位)

(2)DOC、LZH和TXT这些扩展名中,哪一个是压缩文件的扩展名?

LZH   (LZH是用LHA等工具压缩过的文件的扩展名)

(3)文件内容用“数据的值*循环次数”来表示的压缩方法时RLE算法还是哈夫曼算法?

RLE算法

(4)在Windows计算机经常使用的SHIFT JIS字符编码中,1个半角英数是用几个字节的数据来表示的?

1字节=8位

(5)BMP(BITMAP)格式的图像文件,是压缩过的吗?

没有压缩

(6)可逆压缩和非可逆压缩的不同点是什么?

压缩后的数据能复原的是可逆压缩,无法复原的是非可逆压缩。

1 文件以字节位单位保存

文件是将数据存储在磁盘等存储媒介中的一种形式。程序文件中存储数据的单位是字节。文件的大小之所以用xxKB、xxMB等来表示,就是因为文件是以字节(B=Byte)为单位来存储的。

文件就是字节数据的集合。用1字节(=8位)表示的字节数据有256种,用二进制数来表示的话,其范围就是00000000~11111111.如果文件中存储的数据时文字,那么该文件就是文本文件。如果是图形,那么该文件就是图像文件。在任何情况下,文件中的字节数据都是连续存储的。

2 RLE算法的机制

  以示例来描述一下这个压缩机制:AAAAAABBCDDEEEEEF

  由于半角字母中,1个字符是作为1个字节的数据被保存在文件中的。因此上述的文件大小就是17字节。好,那我们现在开始以“

字符*重复次数”这样的表现方式来压缩。上述文件内容就变为A6B2C1D2E5F1来表示,这样只剩12字节,因此结果就将原文件压缩了12字节/17字节=70% 。

  上述的压缩方法称为RLE(Run Length Encoding,行程长度编码)算法。RLE算法是一种很好的压缩算法,经常被用于压缩传真的图像等。因为图像文件本质上也是字节数据的集合体。

3 RLE算法的缺点

  然而,在实际的文本中,同样字符多次重复出现的情况并不多见。虽然针对相同数据经常连续出现的图像、文件等,RLE算法可以发挥不错的效果,但它并不适合文本文件的压缩。不过,因为该压缩机制非常简单,因此使用RLE算法的程序也相对更容易编写。

好,现在就来看一个反例:This is a pen.

这个文本采用RLE算法对其进行压缩后,就变成了T1h1i1s1 1i1s1 1a1p1e1n1.1,这样28个字符,是压缩前的2倍。由于文章中字符大量连续出现的情况并不多见,因此,使用RLE算法后,大部分字符后面都会加上1,这样一来,压缩后的文件自然变成了之前的2倍。

4 通过莫尔斯编码来看哈夫曼算法的基础

   哈夫曼算法是哈夫曼于1952年提出来的压缩算法。

为了更好地理解哈夫曼算法,首先大家要抛弃掉“半角英文数字的1个字节是1个字节(8位)的数据”这个概念。文本文件是由不同类型的字符组合而成的,而且不同的字符出现的次数也是不同的。例如,在某一个文本文件中,A出现了100次左右,Q仅用到了3次,类似这样的情况是很常见的。而哈夫曼算法的关键就在于“多次出现的数据用小于8位的字节数来表示,不常用的数据则可以用超过8位的字节数来表示”。A和Q都用8位来表示时,原文件的大小就是100*8+3*8=824位,而假设A用2位,Q用10位来表示,压缩后的大小就是100*2+3*10=230位。

不过有一点需要注意,不管是不满8位的数据,还是超过8位的数据,最终都要以8位为单位保存到文件中。这时因为磁盘是以字节(8位)为单位来保存数据的。

为了更好地理解哈夫曼算法,先来看一下莫尔斯编码。莫尔斯编码不是通过语言,而是通过“嗒 嘀 嗒 嘀”这些长点和短点的组合来传递文本信息的。

  莫尔斯编码把一般文本中出现频率高的字符用短编码来表示。这里所说的出现频率,不是通过对出版物等文章进行统计调查得来的,而是根据印刷行业的印刷活字数目而确定的。如上表所示,假设表示短点的位是1,表示长点的位时11的话,那么E(嘀)这一字符的数据就可以用1位的1来表示,C(嗒嘀嗒嘀)这一字符的数据就可以用9位的110101101来表示。在实际的莫尔斯编码中。如果短点的长度是1,长点的长度就是3,短点和长点的间隔就是1.这里的长度指的是声音的长度。接下来,就让我们尝试一下用莫尔斯编码来表示前面提到的AAAAAABBCDDEEEEEF这个17个字符的文本。在莫尔斯编码中,各个字符之间需要加入表示间隔的符号。这里我们用00来进行区分。因此,就编程了A*6+B*2+C*1+D*2+E*5+F*1+字符间隔*16=4*6+8*2+9*1+6*2+1*5+8*1+2*16=106位=14字节。因为文件只能以字节位单位来存储数据,因此不满1字节的部分就要圆整成1个字节。如果所有字符占用的空间都是1个字节(8位),这样文本中列出来的17个字符=17字节,那么摩尔斯电码的压缩比率就是14/17=82%。

5 用二叉树实现哈夫曼编码

  哈夫曼算法是指,为各压缩对象文件分别构造最佳的编码体系,并以该编码体系为基础来进行压缩。因此,用什么样式的编码(哈夫曼编码)对数据进行分割,就要由各个文件而定。用哈夫曼算法压缩过的文件中,存储着哈夫曼编码信息和压缩过的数据,如下图:

  接下来,我们尝试一下把AAAAAABBCDDEEEEEF这些字符按照“出现频率高的字符用尽量少的位数编码来表示”这一原则进行整理。我们假定用下面的方案:

  在上述的方案中,随着出现频率的降低,字符编码信息的数据位数也在逐渐增加,从开始的1位、2位依次增加到3位。不过这个编码体系是存在问题的,假设100这个3位的编码,它的意思是用1、0、0这3个编码来表示E、A、A呢?还是用10、0这两个编码来表示B、A呢?亦或是用100来表示C呢?这些都无法进行区分。因此,如果不加入用来区分字符的符号,这个编码就无法使用。

而在哈夫曼算法中,通过借助哈夫曼树构造编码体系,即使在不使用字符区分符号的情况下,也可以构建能够明确进行区分的编码体系。接下来我们就看一下如何制作哈夫曼树。

6 哈夫曼算法能够大幅提升压缩比率

使用哈夫曼树后,出现频率越高的数据所占用的数据位数就越少,而且数据的区分也可以很清晰地实现。

通过上一小节的介绍可以发现,在用枝条连接数据时,我们是从出现频率较低的数据开始的,这就意味着出现频率越低的数据到达根部的枝条数就越多,而枝条数越多,编码的位数也就随之增多了。从用哈夫曼算法压缩过的文件中读取数据后,就会以位为单位对该数据进行排查,并与哈夫曼树进行比较看是否到达了目标编码,这就是为什么哈夫曼算法可以对数据进行区分的原因。例如,10001这个使用上图所示的哈夫曼编码作成的5位数据,到达100时,对照哈夫曼树的数据,该数据表示的是B这个字符。好,介绍了这么多,让我们可以来看看哈夫曼算法的压缩比率:

用哈夫曼编码表示AAAAAABBCDDEEEEEF:0000000000001001001101011010101010101111,40位,压缩前位17字节,目前只需要5个字节,当然,这里不包括哈夫曼编码信息的情况。但这个也实现了很高的压缩比率了。

7 可逆压缩和非可逆压缩

Windows的标准图像数据形式为BMP,是完全未压缩的。除此之外,还有其他各种格式的图像数据形式。比如JPEG、TIFF、GIF格式等。与BMP格式不同的是,这些图像数据都会用一些技法来对数据进行压缩。

在大多数情况下,并不要求压缩后的图像文件必须还原到与压缩前同等的质量。与之相比,程序的EXE文件以及每个字符、数值都具有具体含义的文本文件则必须要还原到和压缩前同样的内容。而对于图像文件来说,即使有时无法还原到压缩前那样鲜明的图像状态,但只要肉眼看不出什么区别,有一些模糊也勉强可以接受。这里,我们把能还原到压缩前状态的压缩称为可逆压缩,无法还原到压缩前状态的压缩称为非可逆压缩。

   JPEG格式和GIF格式的图像文件有一些模糊,是因为他们是非可逆压缩,因此还原后会有一些模糊。而GIF格式的文件虽然是可逆压缩,但因为有色数不能超过256色的限制,所以还原后颜色信息会有一些缺失,进而导致了图像模糊。TIFF格式的图像文件虽然不模糊,但却比原始的BMP格式文件还要大,因为TIFF格式的文件中带有各种标签信息。

时间: 2024-10-19 14:28:58

五:亲自尝试压缩数据的相关文章

第六章 亲自尝试压缩数据

压缩,我知道的是可以把文件变小,压缩后文件不能直接被打开,需要解压后才能使用,而对于图像压缩我是一概不知,当我看完这章后,我知道了文件是字节数据的集合体,是以字节为基本单位存储的,还了解了两种算法,RLE算法和哈夫曼算法. RLE算法是指把文件内容用"数据×循环次数"的形式来表示的压缩方法.例如AABBBBCCDEEEEF用该方法表示为A2B4C2D1E4F1,比原来节省了2个字节(半角文数字的1个字符是表示1个字节),该压缩机制比较简单,适用于图像等,但是对于文本文件来说,同样字符连

linux监测程序、磁盘空间管理,压缩数据及归档数据

ps -ef 显示所有进程,以完整的格式输出kill PID 通过进程号杀掉进程killall http* 结束所有http开头的进程 挂载文件系统:mount -t type device directory -t 参数指定了磁盘被格式化的文件系统类型.vfat: Windows 长文件系统.ntfs: Windows NT.XP.Vista及Win7中广泛使用的高级文件系统.iso9660: 标准CD-ROM文件系统. 卸载文件系统:umount [directory | device]例子

用python+selenium获取北上广深成五地PM2.5数据信息并按空气质量排序

从http://www.pm25.com/shenzhen.html抓取北京,深圳,上海,广州,成都的pm2.5指数,并按照空气质量从优到差排序,保存在txt文档里 #coding=utf-8 from selenium import webdriver from time import sleep class PM: def __init__(self): self.dr = webdriver.Chrome() self.pm25_info = self.get_pm25_info() de

android4.0 USB Camera实例(五补充)jpg压缩

前一篇最后 我们说了一个直接将yuv转成jpg的函数 但是转换没有成功 原函数是yuv420转jpg的 研究了下发现 yuv420隔行扫描的的序列是这样的 YYYY YYYY UVUV 而yuv422的隔行扫描的序列是这样的 YU YV YU YV YU YV 所以将函数作如下修改 static int put_jpeg_yuv420p_memory(unsigned char *dest_image, unsigned char *input_image, int width, int hei

java下实现压缩数据存取

使用Apache Commons Compress实现压缩数据存取,支持格式有XZ,7z,tar,zip,jar,bzip2,gzip等. 例子在 https://commons.apache.org/compress/examples.html 而java se包含gzip功能. InputStream is = new GZIPInputStream(new FileInputStream(file));

iOS五种本地缓存数据方式

iOS五种本地缓存数据方式 iOS本地缓存数据方式有五种:前言 1.直接写文件方式:可以存储的对象有NSString.NSArray.NSDictionary.NSData.NSNumber,数据全部存放在一个属性列表文件(*.plist文件)中. 2.NSUserDefaults(偏好设置),用来存储应用设置信息,文件放在perference目录下. 3.归档操作(NSkeyedArchiver),不同于前面两种,它可以把自定义对象存放在文件中. 4.coreData:coreData是苹果官

14052602(骨骼缩放压缩数据)

[目标] 骨骼缩放压缩数据 [思路] 1 现在的骨骼动画压缩数据格式 压缩块字节流CompressedByteStream 2 FRawAnimSequenceTrack.PosKeys 和 FRawAnimSequenceTrack.ScaleKeys 个数不一定相同 所以最好在要压缩块中就分开存储 那么CompressedTrackOffsets的每块骨骼就要六个单元 3[问题]怎么兼容以前的文件包? 4 如果改成Offset每块骨骼六个单元,就得修改UAnimSequence.Compre

第五章:大数据 の HBase 进阶

本课主题 HBase 读写数据的流程 HBase 性能优化和最住实践 HBase 管理和集群操作 HBase 备份和复制 引言 前一篇 HBase 基础 (HBase 基础) 简单介绍了NoSQL是什么和重点讨论 HBase 数据库的特点,在这一篇会进一步介绍 HBase 的其他特性和机制,比如读写数据的流程,在读写过程中 WAL,MemStore 的作用,还会谈谈一些数据缓存机制,明白在什么场景下需要用那一种缓存策略?如何对频繁使用的数据进行快速响应,从检索上提升查询效率和从内存层面上运用不同

浏览器提示ERR_CONTENT_DECODING_FAILED,Gzip压缩数据无法解压

最近在页面上有个显示数据表格的功能,数据由后台传给前台JS表格插件.数据格式为JSON 由于数据量很大,就想到用GZIP压缩以后传给前台.压缩前,某个表格的数据量达到3M多,用GZIP压缩后就200K左右. 业务流程是:先检查缓存中是否有静态文件,如果没有就从数据库中读出来然后保存成文件.这个过程中,我用GZIP先进行了压缩,然后保存.然后再下次读的时候直接读取这个文件. 问题是,读取静态文件之后浏览器却无法正确解码,报ERR_CONTEN_DECODING_FAILED.我在网上搜索了一下原因