C++封装zlib库

  • 1、zlib简介
  • 2、如何下载zlib库源代码
  • 3、如何安装zlib库
  • 4、zlib代码封装步骤
    • 4.1、编写初始化函数
    • 4.2、编写压缩、解压函数
    • 4.3、编写刷新数据函数
  • 5、结论并附上源代码

1、zlib简介

zlib是提供数据压缩用的函式库,最早是由Jean-loup Gailly与Mark Adler所开发。今天,zlib是一种事实上的业界标准,以至于在标准文档中,zlib和DEFLATE常常互换使用。数以万计的应用程序直接或间接依靠zlib压缩函式库,包括: Linux核心、libpng、Apache、nginx等等。

2、如何下载zlib库源代码

可以通过 zlib官网 去下载最新的源代码
这里附上一份 zlib-1.2.11 源代码

3、如何安装zlib库

在centos7下可以通过一下命令去安装zlib库, 其他Linux发行版或者其他系统的安装方式可以自行查照百度,或者直接使用源代码进行安装

yum install -y zlib zlib-devel

4、zlib代码封装步骤

4.1、编写初始化函数

zlib官方的API中压缩使用deflateInit或者deflateInit2,解压使用inflateInit或者inflateInit2,推荐使用后者,后续我们也是根据后者来对zlib进行一个封装。具体函数如下(位于源代码 zlib.h 文件中):

可以看到,事实上上面几个函数只是一个宏,真正的函数是 deflateInit_、inflateInit_、deflateInit2_、inflateInit2_这四个,压缩的函数位于***inflate.c*** 中,解压的函数位于 deflate.c 文件中。
从图中可以看到 deflateInit2 有6个参数,分别是:

  • strm::zlib压缩流,一个结构体,里面包含了压缩和解压的信息

  • level,:压缩等级(-1: 使用默认压缩等级,源码中是6, 0: 不压缩, 正常1~9, 数值越大压缩强度越大)

  • method,:压缩方法(填默认值Z_DEFLATED就行了)

  • windowBits:类似于选择模式(-(15 ~ 8) : 纯deflate压缩,8 ~ 15 : 带zlib头和尾, > 15 : 带gzip头和尾)

  • memLevel:运行过程中的内存限制(>=1 && <= 9)

  • strategy:压缩策略,有5中可以选择,一般默认的Z_DEFAULT_STRATEGY即可(Z_FILTERED,Z_HUFFMAN_ONLY,Z_RLE,Z_FIXED,Z_DEFAULT_STRATEGY)

    而 inflateInit2 相对简单一点,只有两个参数,分别是 strmwindowBits,含义同上。
    z_stream 结构体定义如图,也是在 zlib.h 文件中。
    我们可以通过 zalloczfreeopaque 这三个参数来设置自己的内存分配器,也可以把他们全部置空,使用系统默认的分配器。于是乎我们可以在类中封装一个初始化函数如下:

int ZlibStream::init(Type type, int level, int window_bits,int memlevel, Strategy strategy)
{assert((level >= 0 && level <= 9) || level == -1);assert((window_bits >= 8 && window_bits <= 15));assert((memlevel >= 1 && memlevel <= 9));memset(&m_zstream, 0, sizeof(m_zstream));m_zstream.zalloc = Z_NULL;m_zstream.zfree = Z_NULL;m_zstream.opaque = Z_NULL;switch (type){case DEFLATE:window_bits = -window_bits;break;case GZIP:window_bits += 16;break;case ZLIB:default:break;}if (m_encode)return deflateInit2(&m_zstream, level, Z_DEFLATED, window_bits,memlevel, (int)strategy);elsereturn inflateInit2(&m_zstream, window_bits);
}

在类中添加两个枚举,使得输入参数更为直观

    /*** brief: 压缩类型*/enum Type{DEFLATE = 0,ZLIB,GZIP};/*** brief: 压缩策略*/enum Strategy{DEFAULT = Z_DEFAULT_STRATEGY,FILTERED = Z_FILTERED,HUFFMAN = Z_HUFFMAN_ONLY,RLE = Z_RLE,FIXED = Z_FIXED};

4.2、编写压缩、解压函数

代码如下,其中主要使用了 deflateinflate 函数,这两个函数的第一个参数都是刚刚初始化的那个 z_stream 结构体,第二个参数可以可以是 Z_NO_FLUSHZ_FINISH,前者表示还有数据要压缩,后者表示已无数据需要压缩,一般用于压缩结尾输出最后的压缩内容。
我们一开始需要设置 z_streamnext_in(指向压缩数据的指针)和 avail_in(压缩数据的长度),而 next_out 则是设置为指向我们输出结果的内存块,相应的 avail_out 则是该内存块的大小。每次调用 deflate 或者 inflate 之后,avail_out 会变成输出内存块剩余的空间大小,在代码中我们也是根据这个值是否为0来判断当次压缩是否完成的。

int ZlibStream::execute(bool encode, const std::vector<iovec>& v)
{int ret = 0;for (size_t i = 0; i < v.size(); i++){m_zstream.avail_in = v[i].iov_len;m_zstream.next_in = (Bytef*)v[i].iov_base;iovec* ivc = nullptr;do{if (m_buffers.empty() || m_buffers.back().iov_len == m_buffSize){iovec vc;vc.iov_base = malloc(m_buffSize);vc.iov_len = 0;m_buffers.push_back(vc);}ivc = &m_buffers.back();m_zstream.avail_out = m_buffSize - ivc->iov_len;m_zstream.next_out = (Bytef*)ivc->iov_base + ivc->iov_len;if (m_encode)ret = deflate(&m_zstream, Z_NO_FLUSH);elseret = inflate(&m_zstream, Z_NO_FLUSH);if (ret == Z_STREAM_ERROR)return ret;ivc->iov_len = m_buffSize - m_zstream.avail_out;}while (m_zstream.avail_out == 0);}return Z_OK;
}

4.3、编写刷新数据函数

代码如下,和之前的压缩执行函数基本一致,只是此时已无数据需要压缩了,则将next_inavail_in 置空,deflateinflate 的第二个参数改为 Z_FINISH,在最后调用 deflateEnd 或者 inflateEnd 来结束本次压缩/解压过程,最终的数据也顺利输出到我们的缓冲区中。(注:输出最后的数据时有可能会出现输出内存不够的情况,所以依然需要循环判断 avail_out 是否用完,这一步是不能省略的)

int ZlibStream::flush()
{int ret = 0;m_zstream.avail_in = 0;m_zstream.next_in = nullptr;iovec* ivc = nullptr;do{if (m_buffers.empty() || m_buffers.back().iov_len == m_buffSize){iovec vc;vc.iov_base = malloc(m_buffSize);vc.iov_len = 0;m_buffers.push_back(vc);}iovec* ivc = &m_buffers.back();m_zstream.avail_out = m_buffSize - ivc->iov_len;m_zstream.next_out = (Bytef*)ivc->iov_base + ivc->iov_len;if (m_encode)ret = deflate(&m_zstream, Z_FINISH);elseret = inflate(&m_zstream, Z_FINISH);if (ret == Z_STREAM_ERROR)return ret;ivc->iov_len = m_buffSize - m_zstream.avail_out;}while (m_zstream.avail_out == 0);if (m_encode)deflateEnd(&m_zstream);elseinflateEnd(&m_zstream);return Z_OK;
}

5、结论并附上源代码

zlib库使用起来还是比较简单,有兴趣的可以去看一下官方的源代码。
这里给出本文的源代码,里面包含一个简单的测试文件,Linux环境下在根目录make即可完成代码编译,然后输入 ./all 执行测试代码(需实现安装g++、make和zlib等依赖环境)
c++zlib简单封装源代码

C++封装zlib库相关推荐

  1. QT4.8.6调用zlib库实现数据流的压缩与解压缩

    转载sunnysab :https://blog.csdn.net/sunnysab/article/details/46672949 ZLIB库 ZLIB版本zlib 1.2.11  地址:http ...

  2. 数据流压缩之应用篇zlib库

    关于数据流压缩的原理,lz77以及huffman编码可以参考上一篇: https://blog.csdn.net/sesiria/article/details/116835301 本篇将包含以下内容 ...

  3. C++ ZIP压缩文件,使用zlib库和codeproject上的zip_utils

    PS; zlib库比较老了,好像是Version 1.01e.基本功能也差不多. part1: 使用codeproject上的完整的库,大牛弄的是真的方便简单. 地址:http://www.codep ...

  4. png库结合zlib库使用出现的一个链接问题的解决

    作者:朱金灿 来源:http://blog.csdn.net/clever101 要使用png库,首先得编译png库,要编译png库,得依赖zlib库的头文件.在使用png库读取一个png文件时,代码 ...

  5. 使用zlib库进行数据压缩

    http://blog.chinaunix.net/uid-14121858-id-216337.html 使用zlib库进行数据压缩 什么是zlib? 官网上有如下说明,自己看吧 zlib is d ...

  6. python2.7中没有zlib库的解决方案(zipimport.ZipImportError: can't decompress data; zlib not available)

    今天遇到个问题,自己安装的python2.7在/opt目录下,运行起来后,发现使用zlib库出错,网上查找后,获得答案 错误提示: zipimport.ZipImportError: can't de ...

  7. 使用zlib库实现gzip格式压缩

    在产品设备上没有gzip压缩命令,但有zlib库,可以根据zlib库很方便的实现gzip压缩.下载zlib的源码,在test目录下面有几个测试程序,根据这几个测试程序基本可以写出想要的程序了.如下是一 ...

  8. zlib库删除后的恢复

    不小心删除了zlib库的下场(rpm -e zlib*) 错误提示: errorwhile loading shared libraries: libz.so.1: cannot open share ...

  9. 心得 ~ 使用 zlib库 解压缩 zip文件

    最近在完成一个项目,需要用到C++语言读取一个zip文件内指定文件的内容.在网上查阅了不少资料,针对过程中遇到的问题,自己也研究了一下,现将方法心得记录下来. 关于解压文件的方法,根据网上的资料,大概 ...

最新文章

  1. 服务器和芯片有什么区别,物联网模块和芯片的区别
  2. 「 每日一练,快乐水题 」917. 仅仅反转字母
  3. LeetCode_树类
  4. MNIST数据可视化
  5. 【第三期】那些设计漂亮、有创意的电路板!
  6. android 电池栏的高度,Android如何取得状态栏、任务栏高度
  7. [PAT乙级]1006 换个格式输出整数
  8. 加载oracle属性文件,关于属性文件的详细介绍
  9. 从Qt4 迁移到Qt5 winEvent代替为nativeEvent
  10. 基于pytorch实现图像分类——理解自动求导、计算图、静态图、动态图、pytorch入门
  11. MySQL FailOver(官方自带,free)
  12. 暴风转码转超清文件_暴风影音16破解版下载-暴风影音16多开精简版(附怎么用) v9.4.1029.1111...
  13. ASP.net网页导出Excel中文乱码解决方案
  14. android开发笔记之reflect使用
  15. PyQt5网易云主页UI实现
  16. 瑞吉外卖01-项目整体介绍
  17. 前端学习路线(前端零基础)
  18. 别让这些遗憾 变成你的遗憾
  19. 《十周成为数据分析师》笔记——业务线 第五节 用户画像体系
  20. 拉勾教育 重学数据结构与算法 08 | 字符串:如何正确回答面试中高频考察的字符串匹配算法?

热门文章

  1. 【同花顺】同花顺解题
  2. git/github教程
  3. 通过经纬度计算两点间的直线距离
  4. 十进制12345在32位计算机中的十六进制表示方法
  5. Reversing.kr-Ransomware
  6. LED电子显示屏真彩显示的几种关键技术[转]
  7. r语言做绘制精美pcoa图_三分钟绘制一张优美的PCoA图 | 云平台
  8. 机器学习项目一:共享单车
  9. zcmu-1931 wjw的剪纸
  10. 鬼谷八荒仙姿男捏脸数据