zlib是一个著名的开源软件包,用于数据压缩 你用这个头可以对自己的程序和文件进行程序内数据压缩、解压 比如,你编写了一个网络程序,不过发现数据量很大,而且搞不好容易被别人截获数据内容,那么你可以对大片的数据用zlib压缩一下,再发送,效果就好多了。
使用方法:
包含zlib.h
连接时指明libz.so路径
compress,compress2为一次将所有串传入的压缩方法
int compress (Bytef *dest, uLongf *destLen,
const Bytef *source, uLong sourceLen);
按照默认级别6压缩字符串
source,输入字符串,要求以‘\0'结尾,sourceLen = strlen(source)
dest 输出字符串,预先分配的空间,在source很短,只有几个byte时,长度需要比source长12个字节
一般情况,可以比较短。一般的压缩率是2~5。
返回值
compress returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_BUF_ERROR if there was not enough room in the output
buffer.
zlib.h:
#define Z_OK 0
#define Z_STREAM_END 1
#define Z_NEED_DICT 2
#define Z_ERRNO (-1)
#define Z_STREAM_ERROR (-2)
#define Z_DATA_ERROR (-3)
#define Z_MEM_ERROR (-4)
#define Z_BUF_ERROR (-5)
#define Z_VERSION_ERROR (-6)
int compress2(Bytef *dest, uLongf *destLen,
const Bytef *source, uLong sourceLen,
int level);
增加压缩级别参数level (1,...,9)
int uncompress (Bytef *dest, uLongf *destLen,
const Bytef *source, uLong sourceLen);
统一解压缩函数,注意传出串的长度
返回值:
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_BUF_ERROR if there was not enough room in the output
buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
其他的使用方法见解压缩后的文件example.c
缓冲区设定方法:
1。修改zlib.h的默认值
2。编译时指定
-DMAX_WBITS=15 -DMAX_MEM_LEVEL=8(默认值)
DMAX_WBITS,窗口宽度,15似乎是最大的了,再高会出错.目前这个值是最好的.
DMAX_MEM_LEVEL 最大是8,小的话对性能有负面影响
分步压缩方法:
将串逐段传入,依次压缩,
http://zlib.net/zlib_how.html 第一个例子便是.
转自:http://blog.chinaunix.net/u1/34978/showart_1146529.html
2)
zlib(http://zlib.net/)提供了简洁高效的In-Memory数据压缩和解压缩系列API函数,很多应用都会用到这个库,其中compress和uncompress函数是最基本也是最常用的。不过很奇怪的是,compress和uncompress函数尽管已经非常的简单,却仍然有不少人用得不好,其实归根结底还是在于有些事情没有弄明白,这里大家先看下面的代码。
3)
头文件 zlib.h
int compress (Bytef * dest , uLongf * destLen, constt Bytef * source , uLongf sourceLen)
zib的压缩函数,将source处sourceLen个字节进行压缩,放到dest指向的内存,把压缩后的长度存入destLen指向的地址中。调用前destLen表示dest缓冲区,调用后destLen表示压缩后的长度。调用前需指定destLen。
return:
Z_OK 成功,
Z_MEM_ERROR 内存不足
Z_BUF_ERROR dest的缓冲区太小
int uncompress(Bytef *dest, uLongf *destLen,const Bytef *source, uLongf sourceLen)
zlib的解压缩函数,将source处sourceLen个字节解压缩,放到大小为destLend的dest缓冲区中,将最终的长度放到destLen指向的地址中。
所以调用前需赋值destLen
return:
Z_OK 成功,
Z_MEM_ERROR 内存不足
Z_BUF_ERROR dest的缓冲区太小
Z_DATA_ERROR 输入数据有误
4)
最近libcurl不能支持毫秒级的超时问题,在第三方接口出现问题的时候由于超时问题容易挂住我们的server,因此考虑自己写一个http协议处理的类,来处理向第三方的http协议接口请求数据的问题。首先一个问题是处理http响应数据经过压缩后的解压问题。这里必然选择zlib库。 使用zlib函数进行解压处理的过程中,一个高级解压函数为inflateInit2,该函数的第二个参数为解压buffer的窗口大小,该参数的一下三种情况支持三种不同的压缩数据解压: 1.8...15 压缩格式为zlib header包裹的deflate原始数据; 2.-8...-15 压缩格式为原始的deflate数据; 3.8...15 + (32) 压缩格式为zlib header或者gzip header包括的deflate原始数据。 第三种情况要求zlib的version大于等于1.2.0.4,如果小于干版本好,那么必须自己处理对应的gzip header,然后再解压原始的deflate数据。写了一个简单的解压函数如下,方便没有接触过zlib的兄弟们了解解压Http Rsp的过程。 uncompress.h #ifndef __UNCOMPRESS_H__ #define __UNCOMPRESS_H__ #include "zlib.h" #include <string> using namespace std; class CUncompress { public: CUncompress(string & sUncompressData); ~CUncompress(); public: int Init(char * pszCompressed, int nCompressedLen, bool bIsGzip=false); int UncompressData(); char * GetErrMsg() { return m_szErrMsg; } private: string & m_sData; char * m_pszDataChunk; z_stream m_objStream; char m_szErrMsg[1024]; bool m_bIsGzip; }; #endif uncompress.cpp #include "uncompress.h" #include <string.h> static const int DSIZE = 0x10000; CUncompress::CUncompress(string & sUncompressData):m_sData(sUncompressData) { memset(m_szErrMsg, 0, 1024); m_pszDataChunk = new char[DSIZE]; m_bIsGzip = false; } CUncompress::~CUncompress() { if (m_pszDataChunk != NULL) { delete [] m_pszDataChunk; } } int CUncompress::Init(char * pszCompressed, int nCompressedLen, bool bIsGzip) { int nErrCode = 0; m_objStream.zalloc = (alloc_func)Z_NULL; m_objStream.zfree = (free_func)Z_NULL; m_objStream.opaque = 0; m_objStream.next_in = NULL; m_objStream.avail_in = 0; if (bIsGzip) { m_bIsGzip = true; if (strcmp(zlibVersion(), "1.2.0.4") < 0) { snprintf(m_szErrMsg, 1024, "zlib version < 1.2.0.4"); return -1; } if ((nErrCode = inflateInit2(&m_objStream, MAX_WBITS + 32)) != Z_OK) { snprintf(m_szErrMsg, 1024, "inflateInit2 failed, err code=%d", nErrCode); return -2; } } else { if ((nErrCode = inflateInit(&m_objStream)) != Z_OK) { snprintf(m_szErrMsg, 1024, "inflateInit failed, err code=%d", nErrCode); return -3; } } m_objStream.next_in = (Bytef*)pszCompressed; m_objStream.avail_in = (uInt)nCompressedLen; return 0; } int CUncompress::UncompressData() { bool bRetry = true; uInt unRead = m_objStream.avail_in; Bytef * pszInData = m_objStream.next_in; int nStatus = 0; for (;;) { m_objStream.next_out = (Bytef*)m_pszDataChunk; m_objStream.avail_out = DSIZE; nStatus = inflate(&m_objStream, Z_SYNC_FLUSH); if (nStatus == Z_OK || nStatus == Z_STREAM_END) { bRetry = false; if (DSIZE - m_objStream.avail_out) { m_sData.append(m_pszDataChunk, DSIZE - m_objStream.avail_out); } if (nStatus == Z_STREAM_END || (nStatus == Z_OK && m_objStream.avail_in == 0)) { if ((nStatus = inflateEnd(&m_objStream)) == Z_OK) { return 0; } else { snprintf(m_szErrMsg, 1024, "inflateEnd failed, err code=%d", nStatus); return -1; } } } else if ((!m_bIsGzip) && bRetry && nStatus == Z_DATA_ERROR) { //if has no zlib header, try another way (void)inflateEnd(&m_objStream); if ((nStatus = inflateInit2(&m_objStream, -MAX_WBITS)) != Z_OK) { snprintf(m_szErrMsg, 1024, "data has no zlib header, try another way inflateInit2 failed, err cod=%d", nStatus); return -2; } m_objStream.next_in = pszInData; m_objStream.avail_in = unRead; bRetry = false; continue; } else { (void)inflateEnd(&m_objStream); snprintf(m_szErrMsg, 1024, "error when inflate compressed, err code=%d", nStatus); return -3; } } return 0; }