热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android培训班(100)内核解压过程13

有了文件的格式,就可以按图索骥,也就是根据文件的格式来分析压缩数据了。但文件格式只是一种存储的格式,还需要算法才可以把数据解压出来

有了文件的格式,就可以按图索骥,也就是根据文件的格式来分析压缩数据了。但文件格式只是一种存储的格式,还需要算法才可以把数据解压出来,下面就来理解gzip的压缩算法。gzip使用deflate的压缩算法来进行压缩数据,这是一种无损的压缩算法,主要组合LZ77和Huffman的压缩算法。

LZ77算法是基于这样的思路:当一串字符中,如果后面的字符串已经在前面出现,那么后面的字符串只需要使用前面的位置和长度就表达相同的字符串,从而达到字符串使用最少的空间。现在看一个简单的例子,如下的字符串:

AABABBBABAABABBBABBABB

在这个串中可以这样表示,第一个块A写作(0,A),第二个块AB,就可以表达为索引和字母的方式(1,B),依这样的编码,就可以得到下面的表格:

索引 块 压缩后表示

1 A (0,A)

2 AB (1,B)

3 ABB (2,B)

4 B (0,B)

5 ABA (2,A)

6 ABAB (5,B)

7 BB (4,B)

8 ABBA (3,A)

9 BB (7,0)

通过这样压缩处理后,就可以减少原来字符串的大小,并且没有数据损失。


Huffman算法是基于这样的思路:当一串字符中,如果某个字符出现的频率越高就使用最短的编码记号,频率越低的就使用最长的编码记号,经过这样编码后达到压缩的目的。可见Huffman算法是基于统计学来压缩的,因此存在码表和统计的过程。不过,Huffman算法也可以采用比较常见的预先定制静态码表来使用,这样就不需要统计的过程了,这种算法叫做静态Huffman算法,反之叫做动态Huffman算法。


有了上面的基础,就可以来学习gunzip函数的代码了,这个函数的代码如下:

/*

*Do the uncompression!

*/

staticint INIT gunzip(void)

{

uch flags;

unsigned char magic[2]; /* magicheader */

char method;

ulg orig_crc = 0; /* originalcrc */

ulg orig_len = 0; /* originaluncompressed length */

int res;


magic[0] = NEXTBYTE();

magic[1] = NEXTBYTE();

这两行代码是获取GZIP压缩的标识字母,用来识别是否GZIP文件的格式。


method = NEXTBYTE();

这行代码是获取什么方式解压,这里使用DEFATED方式。


if (magic[0] != 037 ||

((magic[1]!= 0213) && (magic[1] != 0236))) {

error("bad gzip magic numbers");

return -1;

}

这段代码是判断是否GZIP格式。



/* We only support method #8,DEFLATED */

if (method != 8) {

error("internal error, invalid method");

return -1;

}

这段代码是判断是否为DEFLATED压缩方式。


flags = (uch)get_byte();

if ((flags & ENCRYPTED) != 0) {

error("Input is encrypted");

return -1;

}

if ((flags & CONTINUATION) != 0){

error("Multi part input");

return -1;

}

if ((flags & RESERVED) != 0) {

error("Input has invalid flags");

return -1;

}

这段代码是判断是否使用特殊的标志压缩,如果有用就不能执行,因为这里解压代码比较简单。


NEXTBYTE(); /* Get timestamp */

NEXTBYTE();

NEXTBYTE();

NEXTBYTE();

这段代码跳过四个压缩数据时的时间。


(void)NEXTBYTE(); /* Ignore extraflags for the moment */

(void)NEXTBYTE(); /* Ignore OS typefor the moment */

这段代码是跳过额外的标志和操作系统类型。



if ((flags & EXTRA_FIELD) != 0) {

unsigned len = (unsigned)NEXTBYTE();

len |&#61; ((unsigned)NEXTBYTE())<<8;

while (len--) (void)NEXTBYTE();

}

这段代码把所有额外字段跳过&#xff0c;不作任何处理。



/* Get original file name if it wastruncated */

if ((flags & ORIG_NAME) !&#61; 0) {

/* Discard the old name */

while (NEXTBYTE() !&#61; 0) /* null */ ;

}

这段代码跳过原来压缩文件的名称。



/* Discard file comment if any */

if ((flags & COMMENT) !&#61; 0) {

while (NEXTBYTE() !&#61; 0) /* null */ ;

}

这段代码是跳过所有注释的字符。



/* Decompress */

if ((res &#61; inflate())) {

switch (res) {

case 0:

break;

case 1:

error("invalid compressed format (err&#61;1)");

break;

case 2:

error("invalid compressed format (err&#61;2)");

break;

case 3:

error("out of memory");

break;

case 4:

error("out of input data");

break;

default:

error("invalid compressed format (other)");

}

return -1;

}

这段代码是调用inflate来进行数据解压。


/* Get the crc and original length */

/* crc32 (see algorithm.doc)

* uncompressed input size modulo 2^32

*/

orig_crc &#61; (ulg) NEXTBYTE();

orig_crc |&#61; (ulg) NEXTBYTE() <<8;

orig_crc |&#61; (ulg) NEXTBYTE() <<16;

orig_crc |&#61; (ulg) NEXTBYTE() <<24;

这段代码是获取原来的CRC32检验码&#xff0c;以便跟解压出来的数据计算的CRC32检验码比较。



orig_len &#61; (ulg) NEXTBYTE();

orig_len |&#61; (ulg) NEXTBYTE() <<8;

orig_len |&#61; (ulg) NEXTBYTE() <<16;

orig_len |&#61; (ulg) NEXTBYTE() <<24;

这段代码是获取压缩之前数据长度。


/* Validate decompression */

if (orig_crc !&#61; CRC_VALUE) {

error("crc error");

return -1;

}

if (orig_len !&#61; bytes_out) {

error("length error");

return -1;

}

这段代码是检查CRC32是否对&#xff0c;解压后长度与压缩前的长度是否一致。


return 0;


underrun: /* NEXTBYTE() goto&#39;s hereif needed */

error("out of input data");

return -1;

}



推荐阅读
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 图像因存在错误而无法显示 ... [详细]
  • 合并列值-合并为一列问题需求:createtabletab(Aint,Bint,Cint)inserttabselect1,2,3unionallsel ... [详细]
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
  • 本文分析了Wince程序内存和存储内存的分布及作用。Wince内存包括系统内存、对象存储和程序内存,其中系统内存占用了一部分SDRAM,而剩下的30M为程序内存和存储内存。对象存储是嵌入式wince操作系统中的一个新概念,常用于消费电子设备中。此外,文章还介绍了主电源和后备电池在操作系统中的作用。 ... [详细]
author-avatar
liuc
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有