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

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.gz
cd zlib-1.2.11
./configure
make
make 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然后输出到屏幕。

猜你喜欢

转载自blog.csdn.net/weixin_28712713/article/details/77866177