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然后输出到屏幕。