bzip2库libbzip2使用(三):底层接口
说明
bzip2提供了底层接口、高级接口以及两个实用函数(Utility functions)。本文的主要目的,是说明如何使用底层接口解压数据。
底层接口可以控制每次解压数据的大小,常用在对内存有较高要求的地方。
bz_stream结构体
使用底层接口,需要先定义一个bz_stream
结构体指针,该结构体定义如下:
typedef struct {
char *next_in;
unsigned int avail_in;
unsigned int total_in_lo32;
unsigned int total_in_hi32;
char *next_out;
unsigned int avail_out;
unsigned int total_out_lo32;
unsigned int total_out_hi32;
void *state;
void *(*bzalloc)(void *,int,int);
void (*bzfree)(void *,void *);
void *opaque;
} bz_stream;
该结构体位于bzlib.h
文件中。
在无stdio环境使用库
在嵌入式环境中解压,可以预定义BZ_NO_STDIO,这样编译库时,就会得到只包含实用函数和低级接口的库,高级接口的函数将不被编译。他们分别包括:
类型 | 函数名 |
---|---|
实用函数 | BZ2_bzBuffToBuffCompress,BZ2_bzBuffToBuffDecompress |
低级接口 | BZ2_bzCompressInit,BZ2_bzCompress,BZ2_bzCompressEnd BZ2_bzDecompressInit,BZ2_bzDecompress,BZ2_bzDecompressEnd |
这样编译的函数,将忽略参数verbosity
的值。verbosity
范围0-4,用于控制压缩/解压过程中是否打印信息。
使用
为便于测试,由于PC内存充足,所以直接采用实用接口BZ2_bzBuffToBuffCompress
压缩数据,拿到压缩后的数据流。再采用底层接口解压它。
char buffer[] = "hello world!1234567890hello world!1234567890678ty7t32148776416754327854763214354343231"; //原始数据
int len = strlen(buffer); //原始数据长度
int destLen = len * 1.1 + 600; //压缩后的数据长度,原始数组长度*1.01+600,可以多给一些,保持内存充足。
char* dest = malloc(destLen); //接收压缩过的数据
memset(dest, 0, destLen);
int err; //错误码
//压缩
err = BZ2_bzBuffToBuffCompress(
dest, //目标buffer(压缩后的数据)
&destLen, //目标buffer长度。函数内部压缩完之后,会设置为实际的长度。
buffer, //原始数据
len, //原始数据长度
1, //blockSize100k 字典大小,范围1-9,实际尺寸是100k*N
4, //verbosity 控制台输出压缩信息,范围0-4,数字越小输出越少
30 //默认值30,库内部排序算法相关
);
然后使用底层接口解压dest:
bz_stream strm;
int ret;
int verbosity = 0, small = 1; //small非0时,算法内部会使用另一种解压算法,减少内存的消耗
//使用默认的内存管理函数,如果需要,可以指定为自己提供的内存管理函数
strm.bzalloc = NULL;
strm.bzfree = NULL;
strm.opaque = NULL;
ret = BZ2_bzDecompressInit(&strm, verbosity, small);
if (ret != BZ_OK) return ret;
char decompress[1024] = { 0 }; //提供一个1k的缓存区
int decomLen = 10; //本次输出10字节的解压数据
strm.next_in = dest; //压缩数据
strm.next_out = decompress; //解压存放的地址
strm.avail_in = destLen; //压缩数据的长度
strm.avail_out = decomLen; //解压多少
//解压
err = BZ2_bzDecompress(&strm);
//结束解压
BZ2_bzDecompressEnd(&strm);
经过调研,bzip2不适合用于单片机环境中。它对内存的消耗比较大,而单片机的ram通常比较小,十几kb,二十kb。没法解压。解压初始化函数:BZ2_bzDecompressInit
源代码中,一个DState结构体占的内存就达到55768字节,近54kb。
bsdiff差分升级算法中,使用了bzip2压缩解压。因此无法直接在单片机中使用,若要使用,需要考虑切换压缩算法或切换差分升级算法。