zlib api使用方法摘要[ZT]

来源:互联网 发布:java tarInput 编辑:程序博客网 时间:2024/04/29 15:04

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函数尽管已经非常的简单,却仍然有不少人用得不好,其实归根结底还是在于有些事情没有弄明白,这里大家先看下面的代码。

[cpp] view plaincopy
  1. #include <stdlib.h>  
  2. #include <string.h>  
  3. #include <stdio.h>  
  4. #include <zlib.h>  
  5.   
  6. int main(int argc, char* argv[])  
  7. {  
  8.     char text[] = "zlib compress and uncompress test\nturingo@163.com\n2012-11-05\n";  
  9.     uLong tlen = strlen(text) + 1;  /* 需要把字符串的结束符'\0'也一并处理 */  
  10.     char* buf = NULL;  
  11.     uLong blen;  
  12.   
  13.     /* 计算缓冲区大小,并为其分配内存 */  
  14.     blen = compressBound(tlen); /* 压缩后的长度是不会超过blen的 */  
  15.     if((buf = (char*)malloc(sizeof(char) * blen)) == NULL)  
  16.     {  
  17.         printf("no enough memory!\n");  
  18.         return -1;  
  19.     }  
  20.   
  21.     /* 压缩 */  
  22.     if(compress(buf, &blen, text, tlen) != Z_OK)  
  23.     {  
  24.         printf("compress failed!\n");  
  25.         return -1;  
  26.     }  
  27.   
  28.     /* 解压缩 */  
  29.     if(uncompress(text, &tlen, buf, blen) != Z_OK)  
  30.     {  
  31.         printf("uncompress failed!\n");  
  32.         return -1;  
  33.     }  
  34.   
  35.     /* 打印结果,并释放内存 */  
  36.     printf("%s", text);  
  37.     if(buf != NULL)  
  38.     {  
  39.         free(buf);  
  40.         buf = NULL;  
  41.     }  
  42.   
  43.     return 0;  
  44. }  
zlib处理的对象是Bytef*字节流,很多人遇到字符串就会混淆了,其实很简单,字节流是没有结束符的,需要配备长度信息,所以处理字符串的时候需要把结束符也当成一个普通的字节,这样计算长度的时候也需要算它一份。另外绝大部分人都想动态分配缓冲区,也就是说需要多少再给多少,其实zlib本身有提供compressBound函数用于计算压缩后缓冲区长度的上限值,不需要额外再设计一些不适当的预测算法,不过解压缩的时候没有提供长度的预测,由于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;}



0 0
原创粉丝点击