Loading

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压缩解压。因此无法直接在单片机中使用,若要使用,需要考虑切换压缩算法或切换差分升级算法。

posted @ 2023-01-28 16:12  sq800  阅读(553)  评论(0编辑  收藏  举报