bzip数据压缩 C调用

来源:互联网 发布:怎么用淘宝客赚钱 编辑:程序博客网 时间:2024/04/29 19:16


bzip官网:http://www.bzip.org/  有源码及英文文档。


官网的英文文档比较齐全,可就是没有找到类似的demo代码,没办法,只能结合已有的官方文档,自己摸索了。

由于需要对内存的数据进行加压解压处理,因此调用的是bzip提供的低级接口:

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;int BZ2_bzCompressInit ( bz_stream *strm,                          int blockSize100k,                          int verbosity,                         int workFactor );//一般使用默认推荐参数:BZ2_bzCompressInit(strm,5,2,30);int BZ2_bzCompress ( bz_stream *strm, int action );int BZ2_bzCompressEnd ( bz_stream *strm );int BZ2_bzDecompressInit ( bz_stream *strm, int verbosity, int small );// 一般使用默认推荐参数:BZ2_bzDecompressInit(strm,2,1);int BZ2_bzDecompress ( bz_stream *strm );int BZ2_bzDecompressEnd ( bz_stream *strm );

压缩过程:

1. 初始化压缩参数,分配资源。

2. 对数据进行压缩,输出压缩后的数据。

    压缩的过程实际上是一个有限状态机处理过程,看英文文档感觉比较绕,比较麻烦。

3. 销毁释放分配的资源。



压缩过程的有限状态机:

RUNNING   - 输入数据进行压缩。

FLUSHING  - 输出压缩后的数据。

FINISHING - 没有输入,只有输出。

IDLE      - 压缩未开始或者压缩结束。



压缩遵循的原则:
  

  1. 进入压缩,即进入RUNNING状态,输入待压缩数据,如果BZ2_bzCompress ( bz_stream *strm, int action )返回BZ_RUN_OK,则继续输入。直到返回非BZ_RUN_OK或者没有更多的输入。

  2. 如果上面返回的是BZ_FLUSH_OK,进入FLUSHING状态,输出压缩后的数据。

  3. 如果返回的是BZ_FINISH_OK,进入FINISHING状态,进行输出,直到返回BZ_STREAM_END结束。


  在压缩的过程中,如果出现错误或者异常,如果捕获到其他异常,压缩过程应该就是失败的了。具体异常返回查看BZIP官网。



解压过程也是类似的。
下面直接上代码:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include "bzlib.h"#define BZ_GROUP_MAX_LENGTH10240//#define BZ_DEBUG(format,args...){fprintf(stderr,format,args);}#define BZ_DEBUG(format,args...){}int my_bz_compress(char *src,int *src_len,char *dst,int *dst_len){    int ret = 0;    bz_stream *strm=NULL;    strm = (bz_stream *)malloc(sizeof(bz_stream));    if(strm == NULL){BZ_DEBUG("%s malloc (bz_stream) failed!\n","");ret = -1;return ret;    }    memset(strm,0,sizeof(bz_stream));    ret = BZ2_bzCompressInit(strm,5,2,30);    if(ret != BZ_OK){BZ_DEBUG("%s bzcompressinit failed!\n","");ret = -1;return ret;    }    BZ_DEBUG("bzcommpressinit success %s !\n","");        int src_ptr = 0,src_last = *src_len;    int dst_ptr = 0,dst_last = *dst_len;    int src_tmp = 0,dst_tmp = 0;    ret = BZ_RUN_OK;    while(ret == BZ_RUN_OK || ret == BZ_FLUSH_OK || ret == BZ_FINISH_OK){while(ret == BZ_RUN_OK){    if(src_ptr < (*src_len)){//if(strm->avail_in < 1){    src_last = (*src_len) - src_ptr;    src_tmp = src_last > BZ_GROUP_MAX_LENGTH ? BZ_GROUP_MAX_LENGTH : src_last;    strm->avail_in = src_tmp;    strm->next_in = (char *)(src + src_ptr);//}else{//    src_tmp = strm->avail_in;//    strm->next_in = (char *)(src + src_ptr);//}dst_last = (*dst_len) - dst_ptr;dst_tmp = dst_last > BZ_GROUP_MAX_LENGTH ? BZ_GROUP_MAX_LENGTH : dst_last;strm->avail_out = dst_tmp;strm->next_out = (dst+dst_ptr);        ret = BZ2_bzCompress(strm,BZ_RUN);src_ptr = src_ptr + src_tmp - strm->avail_in;dst_ptr = dst_ptr + dst_tmp - strm->avail_out;BZ_DEBUG("runing ret [%d] src_ptr[%d] src_tmp[%d] in[%d] src_len[%d] dst_ptr[%d] dst_tmp[%d] out[%d] dst_len[%d]\n",ret,src_ptr,src_tmp,strm->avail_in,*src_len,dst_ptr,dst_tmp,strm->avail_out,*dst_len);//if(strm->avail_in > 0)  // ret = BZ_FLUSH_OK;    }else{ret = BZ_FINISH_OK;    }}while(ret == BZ_FLUSH_OK){    if(dst_ptr < (*dst_len)){dst_last = (*dst_len) - dst_ptr;dst_tmp = dst_last > BZ_GROUP_MAX_LENGTH ? BZ_GROUP_MAX_LENGTH : dst_last;strm->avail_out = dst_tmp;        strm->next_out = (dst + dst_ptr);ret = BZ2_bzCompress(strm,BZ_FLUSH);dst_ptr = dst_ptr + dst_tmp - strm->avail_out;BZ_DEBUG("flush ret[%d] dst_ptr[%d] dst_tmp[%d] out[%d] dst_len[%d]\n",ret,dst_ptr,dst_tmp,strm->avail_out,*dst_len);    }else{ret = -1;    }}while(ret == BZ_FINISH_OK){    if(dst_ptr < (*dst_len)){dst_last = (*dst_len) - dst_ptr;dst_tmp = dst_last > BZ_GROUP_MAX_LENGTH ? BZ_GROUP_MAX_LENGTH : dst_last;strm->avail_out = dst_tmp;strm->next_out = (dst + dst_ptr);ret = BZ2_bzCompress(strm,BZ_FINISH);dst_ptr = dst_ptr + dst_tmp - strm->avail_out;BZ_DEBUG("finish ret[%d] dst_ptr[%d] dst_tmp[%d] out[%d] dst_len[%d]\n",ret,dst_ptr,dst_tmp,strm->avail_out,*dst_len);    }else{ret = -1;    }}    }    *dst_len = dst_ptr;    BZ2_bzCompressEnd(strm);//destroy bzcommoress    if(ret == BZ_STREAM_END){BZ_DEBUG("bz_compress success %s !\n","");ret = 0;    }else{BZ_DEBUG("bz_compress failed %s !\n","");ret = -1;    }    return ret;}int my_bz_decompress(char *src,int *src_len,char *dst,int *dst_len){    int ret = 0;    if((*src_len) < 1){BZ_DEBUG("src_len is zero %s !\n","");ret = -1;return ret;    }    bz_stream *strm = NULL;    strm = (bz_stream *)malloc(sizeof(bz_stream));    if(strm == NULL){BZ_DEBUG("malloc() bz_stream failed %s !\n","");ret = -1;return ret;    }    memset(strm,0,sizeof(bz_stream));    ret = BZ2_bzDecompressInit(strm,2,1);    if(ret != BZ_OK){BZ_DEBUG("BZ2_bzDecompressInit failed %s !\n","");ret = -1;return ret;    }    BZ_DEBUG("BZ2_bzDecompressInit success %s !\n","");        int src_ptr = 0,src_last = *src_len;    int dst_ptr = 0,dst_last = *dst_len;    int src_tmp = 0,dst_tmp = 0;    ret = BZ_OK;    while(ret == BZ_OK){src_last = (*src_len) - src_ptr;src_tmp = src_last > BZ_GROUP_MAX_LENGTH ? BZ_GROUP_MAX_LENGTH : src_last;strm->avail_in = src_tmp;strm->next_in = (char *)(src + src_ptr);dst_last = (*dst_len) - dst_ptr;dst_tmp = dst_last > BZ_GROUP_MAX_LENGTH ? BZ_GROUP_MAX_LENGTH : dst_last;if(dst_tmp <1){    BZ_DEBUG("dst space is not enough %s !\n","");    ret = -1;    break;}        strm->avail_out = dst_tmp;strm->next_out = (char *)(dst + dst_ptr);        ret = BZ2_bzDecompress(strm);src_ptr = src_ptr + src_tmp - strm->avail_in;dst_ptr = dst_ptr + dst_tmp - strm->avail_out;BZ_DEBUG("decompress:ret[%d] src_tmp[%d] in[%d] src_ptr[%d] src_len[%d] dst_tmp[%d] out[%d] dst_ptr[%d] dst_len[%d]\n",ret,src_tmp,strm->avail_in,src_ptr,*src_len,dst_tmp,strm->avail_out,dst_ptr,*dst_len);//if(strm->avail_out >0)  //  break;    }     *dst_len = dst_ptr;    BZ2_bzDecompressEnd(strm);//destroy bzcommoress    if(ret == BZ_STREAM_END){        BZ_DEBUG("bz_decompress success %s !\n","");        ret = 0;    }else{        BZ_DEBUG("bz_decompress failed %s !\n","");        ret = -1;    }    return ret;}#include <unistd.h>#define TEST_BUF_LEN100*1024int main(int argc ,char ** argv){    char file_path[256];    memset(file_path,0,256);     int ch;    opterr = 0;    while((ch= getopt(argc,argv,"c:vVh"))!=-1){switch(ch){    case 'V':    case 'v':{printf("test bzip v1.0\n");return 0;    }    case 'h':{printf("BZ_OK:[%d]\n",BZ_OK);printf("BZ_RUN_OK:[%d]\n",BZ_RUN_OK);printf("BZ_FLUSH_OK:[%d]\n",BZ_FLUSH_OK);printf("BZ_FINISH_OK:[%d]\n",BZ_FINISH_OK);printf("BZ_STREAM_END:[%d]\n",BZ_STREAM_END);printf("");return 0;    }    case 'c':{strncpy(file_path,optarg,255);break;    }default:{printf("par error!\n");return 0 ;    }}    }    char *buf1 = NULL;    char *buf2 = NULL;    char *buf3 = NULL;        FILE *fp = NULL;    fp = fopen(file_path,"rb");    fseek(fp,0,SEEK_END);    long len = ftell(fp);    printf("file[%s] len[%ld]\n",file_path,len);    buf1 = (char *)malloc(len+1);    buf2 = (char *)malloc(2*len+1);    buf3 = (char *)malloc(2*len+1);    memset(buf1,0,len+1);    memset(buf2,0,2*len+1);    memset(buf3,0,2*len+1);    fseek(fp,0,SEEK_SET);    int ret = fread(buf1,1,len,fp);    printf("fread len[%ld]\n",ret);    fclose(fp);        int src_len,dst_len;    src_len = len;    dst_len = 2*len;    ret = my_bz_compress(buf1,&src_len,buf2,&dst_len);    printf("\nmy_bz_compress ret[%d] src_len[%d] dst_len[%d] len[%d]\n",ret,src_len,dst_len,len);     if(ret != 0)       return 0;    int write_len = dst_len;    src_len = dst_len;    dst_len = 2*len;    ret = my_bz_decompress(buf2,&src_len,buf3,&dst_len);    printf("\nmy_bz_decompress ret[%d] src_len[%d] dst_len[%d] len[%d]\n",ret,src_len,dst_len,len);    //ret = strcmp(buf1,buf3);    //printf("strcmp ret[%d] len_buf1[%d] len_buf3[%d]\n",ret,len,dst_len);    printf("\n===================================\n");    if(len != dst_len ){printf("compress-decompress len is not equal - failed!\n");return 0;    }    for(ret = 0;ret<len;ret++){if(buf1[ret] != buf3[ret]){    printf("strcmp failed! index[%d]\n",ret);    return 0;}    }    printf("compress-decompress success!\n");    printf("pre_len[%d] next_len[%d] rate[%f] multiple[%f]\n",len,src_len,(double)src_len/len,(double)len/src_len);    /* write the result to file */    fp = fopen("./out.bzip2","wb");    fwrite(buf2,1,write_len,fp);    fclose(fp);    return ret;}


此代码可以和C# sharpziplib.dll的bzip压缩, java的commons-compress-1.9(APACH的库) 相互压缩解压缩。

0 0
原创粉丝点击