发博文
正文 字体大小:

zlib库解压函数的使用

(2010-10-19 21:35:32)
标签:

杂谈

分类: 工作天地
最近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;
}



阅读 评论 收藏 转载 打印举报
已投稿到:
  • 评论加载中,请稍候...

       

    验证码: 请点击后输入验证码 收听验证码

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 不良信息反馈 电话:4006900000 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有