寸阳分阴须爱惜,休负春色与时光。这篇文章主要讲述Linux(程序设计):29---Zlib库(数据压缩与解压)相关的知识,希望能为你提供帮助。
一、Zlib库概述
- zlib压缩算法页是对deflate进行的封装,在另一篇文章中我们介绍过了Deflate压缩算法算法,文章最后也提到了zlib压缩算法。具体可以参阅:javascript:void(0)
Zlib库相关函数
- 压缩函数:
- deflateInit : 参数比较少,里面的实现其实是调用的deflateInit2
- deflateInit2: 压缩初始化的基础函数,有很多参数,下面会重点介绍
- deflate : 压缩函数
- deflateEnd : 压缩完成以后,释放空间,但是注意,仅仅是释放 deflateInit 中申请的空 间,自己申请的空间还是需要自己释放
- compress : 全部附加选项默认压缩,内部调用 compress2
- compress2 : 带 level 的压缩方式
- 解压函数:
- inflateInit : 解压初始化函数,内部调用的 inflateInit2
- inflateInit2 : 解压初始化的基础函数,后面重点介绍
- infalte : 解压函数
- inflateEnd : 同 deflateEnd 作用类似
- uncompress : 解压缩
Zlib库的安装
- 进入网页进行下载,下面我们以下载1.2.11版本为例
wget http://www.zlib.net/zlib-1.2.11.tar.gz
- 解压进入目录
tar zxf zlib-1.2.11.tar.gzcd zlib-1.2.11
- 配置
./configure
文章图片
- 编译
make
- 检查
make check
- 安装
sudo make install
【Linux(程序设计):29---Zlib库(数据压缩与解压)】
- 头文件默认安装在/usr/local/include/目录下,动态库文件在/usr/local/lib/目录下
文章图片
编译带有Zlib库的程序二、deflateInit2:初始化函数
- 命令如下,需要带上-lz选项,指明zlib库
gcc -o demo demo.c -lz
文章图片
- 为压缩初始化内部流状态,zalloc,zfree 和 opaque 字段必须在调用之前初始化, 如果 zalloc 和 zfree 被初始化为 Z_NULL,deflateInit 会更新它们而使用默认的分配函数。
- 压缩级别必须为 Z_DEFAULT_COMPRESSION,或者 0 到 9 之间的数;1 表示最快速 度的压缩,9 表示最优压缩,0 不做任何压缩,Z_DEFAULT_COMPRESSION 是速度和最优压缩的折衷 (一般为 6)
- 函数成功返回 Z_OK,如果没有足够的内存则返回 Z_MEM_ERROR,如果不是一个 有效的压缩级别则返回 Z_STREAM_ERROR,版本不兼容则返回 Z_VERSION_ERROR。如果没有错误信 息则 msg 被设置为 0
strm参数三、deflate:压缩函数
- 这个是压缩上下文
- 我们依照官方给的例子进行初始化
strm.zalloc = NULL; strm.zfree = NULL; strm.opaque = NULL; strm.next_in = 你的待压缩数据 strm.next_out = 压缩以后数据存储的 buffer strm.avail_in = 待压缩数据的长度 strm.avail_out = 压缩数据存储 buffer 的长度.
level参数
- 压缩的等级,目前有四个值
#define Z_NO_COMPRESSION 0 //不压缩 #define Z_BEST_SPEED 1 //速度优先,可以理解为最低限度的压缩 #define Z_BEST_COMPRESSION 9 //压缩优先,但是速度会有些慢 #define Z_DEFAULT_COMPRESSION (-1) //默认选项,compress 里面用的就是这个选 项
method参数
- 值只有一个,当前唯一的 defalte 压缩方法,用于以后扩展
#define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */
windowsBits参数
- 窗口比特数
-(15 ~ 8) : 纯 deflate 压缩 +(15 ~ 8) : 带 zlib 头和尾 > 16 : 带 gzip 头和尾
memLevel参数
- 目前只有一个选项,MAX_MEM_LEVEL,无非是运行过程中对内存使用的限制
/* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL # ifdef MAXSEG_64K # define MAX_MEM_LEVEL 8 # else # define MAX_MEM_LEVEL 9 # endif #endif
strategy参数
- 用于调整压缩算法,直接给默认就行 Z_DEFAULT_STRATEGY.
#define Z_FILTERED 1 //用于由 filter(或者称为 predictor)生成的数据 #define Z_HUFFMAN_ONLY 2 //用于强制哈夫曼编码(不做字符匹配) #define Z_RLE 3 //限制匹配长度为 1 #define Z_FIXED 4 //阻止使用动态哈夫曼编码,从而允许获得更简单的解码 #define Z_DEFAULT_STRATEGY 0 //用于普通数据 /* compression strategy; see deflateInit2() below for details */
- Z_FILTERED,用于由 filter(或者称为 predictor)生成的数据.过滤的数据包含很多小的 随机数据。这种情况下,压缩算法能够获得更好的压缩效果。该选项可以强制更多的哈夫曼编码和更少的字符匹配 。有时候可以作为Z_DEFAULT_STRATEGY 和 Z_HUFFMAN_ONLY 的折中
- Z_FIXED,阻止使用动态哈夫曼编码,从而允许获得更简单的解码
- strategy 参数只影响压缩比,而不会影响到压缩输出的正确性,因此没有正确的设置也 不要紧
文章图片
- deflate 函数尽可能的压缩数据,当输入缓冲为空或者输出缓冲满了的时候会停止。 它会带来输出延迟(读输入数据而没有输出)除非强行刷新缓冲区。
- 详细的语意如下,deflate 会执行下面的一个或者两个动作都执行:
- 从 next_in 开始压缩输入数据从而更新 next_in 和 avail_in。如果不是所有输入数 据可以被处理(因为输出缓冲没有足够的空间),next_in 和 avail_in 会更新,当 再次调用 deflate()函数时输入数据会从这一点开始被处理
- 从 next_out 开始提供更多输出数据从而更新 next_out 和 avail_out,如果 flush 参数不是为 0 的化这个动作是强制性的,经常性的强制刷新缓冲区会降低压缩 比率,所以只有必要的时候才会设置这个参数(在交际程序时),一些数据也会 输出即使刷新没有被设置
- 在调用 deflate()函数之前,应用程序必须保证至少上面的一个动作被执行(avail_in 或 avail_out 被设置),用提供更多输入数据和/或消耗更多输出数据的方式,从而更新 avail_in 或 avail_out;avail_out 在函数调用之前千万不能为 0。应用程序可以随时消耗被 压缩的输出数据,举个例子:当输出缓冲满了或者在每次调用 deflate()之后,如果 deflate 返回 Z_OK 并 avail_out 为 0 时,deflate()必须再次被调用(说明输出缓存区还有数据应 该被读取)。
- flsuh参数:
- Z_NO_FLUSH:通常设置为该值,允许压缩算法决定累积多少数据再产生输出,以达到压缩效率最高。
- Z_SYNC_FLUSH:将所有等待输出的数据刷新到输出缓冲区,以字节为边界进行对 齐。该刷新可能会降低压缩算法的压缩效率,它只用于必要的时候。This completes the current deflate block and follows it with an empty stored block that is three bits plus filler bits to the next byte, followed by four bytes (00 00 ff ff).
- Z_FINISH:如果输入和待输出的数据都被处理完,则返回 Z_STREAM_END。如果返 回 Z_OK or Z_BUF_ERROR 则需要再次调用 Z_FINISH 直到返回 Z_STREAM_END
- Z_NO_FLUSH:通常设置为该值,允许压缩算法决定累积多少数据再产生输出,以达到压缩效率最高。
文章图片
- 压缩完成以后,释放空间,但是注意,仅仅是释放 deflateInit 中申请的空间,自己 申请的空间还是需要自己释放。
文章图片
-
参数:
- strm:和 deflate 一样,初始化三个回调以后即可,有的参考文档说还需要初始化第四个 选项,具体记不清哪个了
- windownBits:含义和 deflateInit2 一样,而且一定要对应起来
文章图片
- strm参数,初始化如下
strm.next_in = 你的待解压数据
strm.next_out = 解压以后数据存储的 buffer
strm.avail_in = 待解压数据的长度
strm.avail_out = 解压数据存储 buffer 的长度.
- flush:和 deflate 一样,如果是 Z_NO_FLUSH 说明还有数据没有解压,如果是 Z_FINISH 说明这是最后一包待解压数据
文章图片
- 释放上面两步骤里面申请的资源
- 源码Github链接:https://github.com/dongyusheng/csdn-code/tree/master/zlib
-
目录下有三个目录:
- deflate:压缩测试源码(本演示案例要用的)
- inflate:解压测试源码
- testfile:用来压缩和解压的测试代码
文章图片
演示案例九、解压演示案例
- 进入deflate目录之后,编译程序
g++ -o deflate deflate.cpp DeflatingStream.cpp -lz
- 下面我们对testfile/目录下的testfile3文件进行压缩,压缩之后的文件名为 testfile3.gz
文章图片
- 压缩完成之后查看一下文件,可以看到文件从2.4k压缩到了559bit
文章图片
- 源码Github链接:https://github.com/dongyusheng/csdn-code/tree/master/zlib
-
目录下有三个目录:
- deflate:压缩测试源码
- inflate:解压测试源码(本演示案例要用的)
- testfile:用来压缩和解压的测试代码
文章图片
演示案例十、总结
- 进入inflate目录之后,编译程序
g++ -o inflate InflatingStream.cpp inflate.cpp -lz
- 接着上面压缩的演示案例,我们对testfile/目录下的testfile3.gz文件进行解压,压缩之后的文件名为testfile3.cpp
文章图片
- 解压完成之后查看一下文件,可以看到文件恢复到了原来的样子
文章图片
- Zlib压缩工具也都是调用这个库实现的,我们也可以自己实现解压缩算法
- 在“数据流压缩原理”压缩文章中(javascript:void(0)),我们曾演示过哈夫曼解压缩编码演示案例,但是效率比较低。本文上面两个演示案例可以看到我们可以看到直接调用Zlib库进行解压缩效率是十分高的
推荐阅读
- 手把手教学,以源码方式在Linux下编译安装消息队列ZeroMQ
- 五mysql存储引擎
- oeasy教您玩转vim - 31 - # 文字区块
- 如何在Ubuntu 16.04中从头开始安装PHPMyAdmin
- 如何使用Google Chrome中的JavaScript检测你是否处于隐身模式
- 如何使用JavaScript在你的网站上实施暴风雪(Snow Effect)
- 如何在Ubuntu 16.10中安装XAMPP
- 如何使用浏览器中的JavaScript防止破坏者被发现
- 如何在Windows中使用Python重新启动本地或网络计算机