zlib

1. zlib库介绍

  • zlib是一套通用的解压缩开源库,提供了内存(in-memory)压缩和解压函数,能检测解压出来的数据完整性,zlib 也支持读写 gzip (.gz) 格式的文件,可以阅读:zlib库介绍三:gzip(.gz格式)文件读写
  • 默认且目前仅使用deflate算法压缩data部分;deflate是一种压缩算法,是huffman编码的一种加强。

2. zlib库的应用

数以万计的应用程序直接或间接依靠zlib压缩函式库,包括:

  • FFmpeg:以zlib读写Matroska等以DEFLATE算法压缩的多媒体串流格式。
  • OpenSSH、OpenSSL:以zlib达到最佳化加密网络传输。
  • Linux核心:使用zlib以实作网络协定的压缩、档案系统的压缩以及开机时解压缩自身的核心。
  • libpng,用于PNG图形格式的一个实现,对bitmap数据规定了DEFLATE作为流压缩方法。
  • 略、、、、

参考博文:zlib库介绍一:zlib简介

3. 下载地址

4. 函数使用教程

zlib 在 examples 路径下提供了许多使用zlib的例子:

在这里插入图片描述
在README.examples 有介绍各个example的作用。

4.1 compress 与 uncompress

compress和uncompress是zlib最基本的两个函数了。他们分别用于压缩和解压数据。 原型如下:

int compress(unsigned char* dest,
			 unsigned long*destLen, 
			 const unsigned char* source, 
			 unsigned long sourceLen);

int compress2(unsigned char* dest, 
			 unsigned long*destLen, 
			 const unsigned char* source,
			 unsigned long sourceLen, 
			 int level);

参数:

  • dest:压缩之后的数据缓冲区。
  • desLen:压缩之后的数据缓冲区长度。
  • source:原始数据缓冲区(压缩之前的数据内容)。
  • sourceLen:原始数据长度。
  • level:level:压缩比例,压缩级别取值:0 - 9。0压缩速度最快,9压缩速度最慢,压缩率最大。0表示不进行压缩。【compress2才有】

返回值:

  • Z_OK:成功。
  • Z_MEM_ERROR:没有足够的内存。
  • Z_BUF_ERROR:输出的缓冲区没有足够的空间。
  • Z_STREAM_ERROR:level参数设置不正确。【compress2才有】
int uncompress(unsigned char* dest, 
				unsigned long* destLen,
				unsigned char* source, 
				unsigned long sourceLen);
				
int uncompress2(unsigned char* dest,
				unsigned long* destLen,
				unsigned char* source, 
				unsigned long* sourceLen);

参数:

  • dest:解缩之后的数据缓冲区

  • desLen:解缩之后的数据缓冲区长度

  • source:要解压的数据缓冲区

  • sourceLen:要解压的数据长度

返回值:

  • Z_OK:成功。

  • Z_MEM_ERROR:没有足够的内存。

  • Z_BUF_ERROR:输出的缓冲区没有足够的空间。

  • Z_DATA_ERROR:输入的原始数据(source)被损坏了,或不完整。

uncompress2函数相比于uncompress函数,原始数据长度采用指针进行表示。

4.3 使用过程解析

  1. 压缩、解压过程 方案一

压缩:deflateInit() ->deflate() ->deflateEnd();

解压:inflateInit() -> inflate() -> inflateEnd();

  1. 压缩、解压过程 方案二

压缩:deflateInit2() ->deflate() ->deflateEnd();

解压:inflateInit2() -> inflate() -> inflateEnd();

ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
                                 const Bytef *source, uLong sourceLen));
ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
                                   const Bytef *source, uLong sourceLen));

参数类型

  • Bytef表示字节流,它与字符串有所不同,字节流没有结束符,因而需要配备长度信息,处理字符串的时候需要把结束符也当成一个普通的字节。
  • uLongf则用于指明长度信息了, 其实相当于unsigned long。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
#include <zlib.h>
 
 
int main(int argc, char *argv[])
{ 
    char inbuf[] = "Hello, This is a demo for compress and uncompress interface!\n"
                 "Written by windeal.li\n"
                 "email: 2378264731@qq.com\n";
    uLong inlen = sizeof(inbuf);
    char *outbuf = NULL;
    uLong outlen;
 
    outlen = compressBound(inlen);
    printf("in_len: %ld\n", inlen);
    printf("out_len: %ld\n", outlen);
 
    if ((outbuf = (char *)malloc(sizeof(char) * outlen)) == NULL){
        fprintf(stderr, "Failed to malloc memory for outbuf!\n");
        return -1;
    }
 
    /* compress */
    if (compress(outbuf, &outlen, inbuf, inlen) != Z_OK) {
        fprintf(stderr, "Compress failed!\n");
        return -1;
    }
    printf("Compress Sucess!\n");
    printf("\routlen:%ld, outbuf:%s\n", outlen, outbuf);
  
    memset(inbuf, 0, sizeof(inbuf));
    /* Uncompress */
    if (uncompress(inbuf, &inlen, outbuf, outlen) != Z_OK){
        fprintf(stderr, "Uncompress failed!\n");
        return -1;
    }
    printf("Uncompress Success!\n");
    printf("\rinlen:%ld, inbuf:%s\n", inlen, inbuf);
 
    /* free memory */
    if (outbuf != NULL){
        free(outbuf);
        outbuf = NULL;
    }
 
    return 0;
}

4.2 infate、deflate、z_stream

这里infate 和defate 其实是指两组函数

  • deflateInit() + deflate() + deflateEnd()用于完成流的压缩
  • inflateInit() + inflate() + inflateEnd()用于完成解压缩功能
int deflateInit (z_streamp strm, int level);  //初始化压缩状态,关联相关的z_stream数据结构和压缩比例
int deflate (z_streamp strm, int flush);   //压缩数据,  flush表示以何种方式将压缩的数据写到缓冲区中。
int deflateEnd (z_streamp strm);    //压缩结束

int inflateInit (z_streamp strm);        
int inflate (z_streamp strm, int flush);
int inflateEnd (z_streamp strm); 

z_stream是上面两组函数中用到的,用来表示流的数据结构。

typedef struct z_stream_s {
    z_const Bytef *next_in;   // 将要压缩数据的首地址
    uInt     avail_in;  // 将要压缩数据的长度
    uLong    total_in;  // 将要压缩数据缓冲区的长度
 
    Bytef    *next_out;  // 压缩后数据保存位置。
    uInt     avail_out; // 压缩后数据的长度
    uLong    total_out; // 压缩后数据缓冲区的大小
 
    z_const char *msg; // 存放最近的错误信息,NULL表示没有错误
    struct internal_state FAR *state; /* not visible by applications */
 
    alloc_func zalloc;  /* used to allocate the internal state */
    free_func  zfree;   /* used to free the internal state */
    voidpf     opaque;  /* private data object passed to zalloc and zfree */
 
    int     data_type;   // 表示数据类型,文本或者二进制
    uLong   adler;      /* adler32 value of the uncompressed data */
    uLong   reserved;   /* reserved for future use */
} z_stream;    

关于这两组函数的具体使用, zlib-1.2.11/examples/zpipe.c或zlib-1.2.11/test/example.c,可以直接参考。

参考博文:

zlib库 安装与使用

zlib库使用简单讲解

5. 交叉编译zlib库

linux主机:ubuntu-18.04

交叉编译器:arm-buildroot-linux-gnueabihf

开发板kernel:Linux 5.4.0-150-generic x86_64

开发板:100ASK_STM32MP157_PRO开发板

zlib版本:zlib-1.2.11.tar.gz


下载

zlib-1.2.11.tar.gz

解压

tar xvf zlib-1.2.11.tar.gz

引入交叉编译器【zlib的configure不支持设置–host项】

export CC=/home/book/100ask_stm32mp157_pro-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/arm-buildroot-linux-gnueabihf-gcc

除了上面的引入交叉编译器,也可以手动更改Makefile,vim命令打开Makefile文件,将其中的CC、AR、RANLIB等都修改为arm-linux交叉编译器的相关参数

配置configure,指定安装后的文件在install文件夹里面

./configure --prefix=$PWD/install

在这里插入图片描述

编译

make

在这里插入图片描述

安装

sudo make install

在这里插入图片描述
由于前面运行configure文件的时候指定了安装的路径

cd install/lib

lib库里面包含静态库和动态库,注意软连接

book@100ask:~/Desktop/zlib/zlib-1.2.11/install/lib$ ls -lath
total 248K
drwxrwxr-x 5 book book 4.0K Jun 18 21:46 ..
drwxrwxr-x 2 book book 4.0K Jun 18 21:46 pkgconfig
drwxrwxr-x 3 book book 4.0K Jun 18 21:46 .
lrwxrwxrwx 1 book book   14 Jun 18 21:46 libz.so -> libz.so.1.2.11
lrwxrwxrwx 1 book book   14 Jun 18 21:46 libz.so.1 -> libz.so.1.2.11
-rwxr-xr-x 1 book book 120K Jun 18 21:46 libz.so.1.2.11
-rw-r--r-- 1 book book 113K Jun 18 21:46 libz.a

检查编译结果

file libz.so.1.2.11 

在这里插入图片描述

使用zlib的接口,只需在 链接命令后加-lz /usr/llocal/lib/libz.a 即可。

gcc -o zpipe.o -c zpipe.c
gcc -o zpipe zpipe.o -lz /usr/local/lib/libz.a 

参考博文:zlib开发笔记(三):zlib库介绍、在ubuntu上进行arm平台交叉编译

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐