centos下使用zlib库支持gzip流解压

来源:互联网 发布:海康网络键盘怎么用 编辑:程序博客网 时间:2024/06/03 02:54

1.简介

zlib是提供数据压缩用的函式库,由Jean-loup Gailly与Mark Adler所开发,初版0.9版在1995年5月1日发表。zlib使用DEFLATE算法,最初是为libpng函式库所写的,后来普遍为许多软件所使用。此函式库为自由软件,使用zlib授权。截至2007年3月,zlib是包含在Coverity的美国国土安全部赞助者选择继续审查的开源项目。

2.下载安装

下载地址:http://www.zlib.net/
我下载的是zlib-1.2.11.tar.gz,然后执行如下命令:

tar -zxvf zlib-1.2.11.tar.gzcd zlib-1.2.11./configuremakemake install

如果要编译成动态库,则只需要第一步改成./configure -s即可。
当当前目录下的.h都保存到自己要使用的地方。还有libz.a也是,这里使用的是静态库。

3.代码使用

我统一把.h放在了代码所在的当前目录下的include文件夹中
3.1 myzlib.h

#ifndef _MYZLIB_H_#define _MYZLIB_H_#include <iostream>#include <cstring>#include <cstdio>#include <cstdlib>#include <string>#include "./include/zlib.h"using namespace std;class MyZlib{public:    MyZlib();    MyZlib(const string& filename);    ~MyZlib();    bool mygzread();    int gzcompress(Bytef *data, uLong ndata,    Bytef *zdata, uLong *nzdata);    int gzdecompress(Byte *zdata, uLong nzdata,            Byte *data, uLong *ndata);private:    string m_filename;    gzFile m_fp;    char m_data[256];};#endif

3.2 myzlib.cpp

#include "myzlib.h"MyZlib::MyZlib():m_fp(NULL){        memset(m_data,0,sizeof(m_data));}MyZlib::MyZlib(const string& filename):m_filename(filename),m_fp(NULL){    memset(m_data,0,sizeof(m_data));}MyZlib::~MyZlib(){    gzclose(m_fp);}/*bool MyZlib::mygzread(){    m_fp = gzopen(m_filename.c_str(),"rb");    if(!m_fp)    {        perror("open file error");        exit(-1);    }    gzseek(m_fp,0,SEEK_END);    unsigned long len = gztell(m_fp);    gzseek(m_fp,0,SEEK_SET);    while(!gzeof(m_fp)){        memset(m_data,0,sizeof(m_data));        gzread(m_fp,m_data,sizeof(m_data));        m_data[255]='\0';        cout<<m_data<<" ";    }    return 1;}*//* Compress gzip data *//* data 原数据 ndata 原数据长度 zdata 压缩后数据 nzdata 压缩后长度 */int MyZlib::gzcompress(Bytef *data, uLong ndata,               Bytef *zdata, uLong *nzdata){    z_stream c_stream;    int err = 0;    if (data && ndata > 0) {        c_stream.zalloc = NULL;        c_stream.zfree = NULL;        c_stream.opaque = NULL;        //只有设置为MAX_WBITS + 16才能在在压缩文本中带header和trailer        if (deflateInit2(&c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,                         MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY) != Z_OK) return -1;        c_stream.next_in = data;        c_stream.avail_in = ndata;        c_stream.next_out = zdata;        c_stream.avail_out = *nzdata;        while (c_stream.avail_in != 0 && c_stream.total_out < *nzdata) {            if (deflate(&c_stream, Z_NO_FLUSH) != Z_OK) return -1;        }        if (c_stream.avail_in != 0) return c_stream.avail_in;        for (;;) {            if ((err = deflate(&c_stream, Z_FINISH)) == Z_STREAM_END) break;            if (err != Z_OK) return -1;        }        if (deflateEnd(&c_stream) != Z_OK) return -1;        *nzdata = c_stream.total_out;        return 0;    }    return -1;             }/* Uncompress gzip data *//* zdata 数据 nzdata 原数据长度 data 解压后数据 ndata 解压后长度 */int MyZlib::gzdecompress(Byte *zdata, uLong nzdata,                 Byte *data, uLong *ndata){    int err = 0;    z_stream d_stream = { 0 }; /* decompression stream */    static char dummy_head[2] = {        0x8 + 0x7 * 0x10,        (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,    };    d_stream.zalloc = NULL;    d_stream.zfree = NULL;    d_stream.opaque = NULL;    d_stream.next_in = zdata;    d_stream.avail_in = 0;    d_stream.next_out = data;    //只有设置为MAX_WBITS + 16才能在解压带header和trailer的文本    if (inflateInit2(&d_stream, MAX_WBITS + 16) != Z_OK) return -1;    //if(inflateInit2(&d_stream, 47) != Z_OK) return -1;    while (d_stream.total_out < *ndata && d_stream.total_in < nzdata) {        d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */        if ((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_STREAM_END) break;        if (err != Z_OK) {            if (err == Z_DATA_ERROR) {                d_stream.next_in = (Bytef*)dummy_head;                d_stream.avail_in = sizeof(dummy_head);                if ((err = inflate(&d_stream, Z_NO_FLUSH)) != Z_OK) {                    return -1;                }            }            else return -1;        }    }    if (inflateEnd(&d_stream) != Z_OK) return -1;    *ndata = d_stream.total_out;    return 0;                 }

3.3 main.cpp

#include "myzlib.h"#include <iostream>#include <cstdio>#include <cstring>using namespace std;const ulong Buffsize=128;int main(){    /*string filename = "zran.tar.gz";    MyZlib myzlib(filename);    bool flag = myzlib.mygzread(buff);    if(!flag){        cout<<"读取错误";    }*/    char data[128];    gzFile fp = NULL;    fp = gzopen("zran.tar.gz","rb");    gzseek(fp,0,SEEK_END);    unsigned long len = gztell(fp);    gzseek(fp,0,SEEK_SET);    cout<<"file len:"<<len<<endl;    while(!gzeof(fp)){        memset(data,0,sizeof(data));        gzread(fp,data,128);        data[128] = '\0';        cout<<data;    }    gzclose(fp);}

然后使用如下命令编译:

g++ -o target main.cpp myzlib.cpp libz.a

注:代码中gzcompress和gzdecompress是直接在流中压缩和解压,不写入文件。
你可以找个tar.gz的文件来试下了。我直接将某个.c或者.cpp文件压缩成zran.tar.gz然后输出到屏幕。