zlib封装C++类
#pragma once
#include <string>
#include <memory>
#include <zlib.h>
/*
to (de-)compress deflate format, use wbits = -zlib.MAX_WBITS
to (de-)compress zlib format, use wbits = zlib.MAX_WBITS,
gzlib header:
0x78 0x01 - No Compression/low
0x78 0x9C - Default Compression
0x78 0xDA - Best Compression
to (de-)compress gzip format, use wbits = zlib.MAX_WBITS | 16
gzip header:0x1F 0x8B
*/
class ZlibHandler
{
public:
ZlibHandler() :
m_nCacheSize (1024 * 1024),
m_nErrCode(Z_OK),
m_mode(0)
{
m_pCacheBuf = new char[m_nCacheSize];
m_bFreeCacheBuf = true;
}
//使用外部缓冲区
ZlibHandler(char *cachebuf, size_t cachesize) :
m_pCacheBuf(cachebuf),
m_nCacheSize(cachesize),
m_bFreeCacheBuf(false),
m_nErrCode(Z_OK),
m_mode(0) {}
~ZlibHandler()
{
if (m_mode == 1)
deflateEnd(&m_zlibStream);
else if (m_mode == 2)
inflateEnd(&m_zlibStream);
m_mode = 0;
if (m_bFreeCacheBuf)
delete[] m_pCacheBuf;
}
/*
* 初始化压缩方法
* 不能同时初始化压缩和解压两个控制器
* 参数:
windowBits = MAX_WBITS + 16 //默认是gzip,如果需要是zlib传入MAX_WBITS即可
*/
bool InitCompress(int windowBits = MAX_WBITS + 16, int level = Z_DEFAULT_COMPRESSION,
int method = Z_DEFLATED, int memLevel = 8, int strategy = Z_DEFAULT_STRATEGY)
{
if (m_mode != 0)
return false;
if (deflateInit2(&m_zlibStream, level, method, windowBits, memLevel, strategy) != Z_OK)
return false;
m_windowbits = windowBits;
m_mode = 1;
return true;
}
/*
* 销毁压缩控制器
* 一般情况下不需要主动调用,除非是上一次压缩数据结束了需要再次压缩新数据,先End再次Init(不推荐)
*/
void CompressEnd()
{
if (m_mode == 1)
{
deflateEnd(&m_zlibStream);
m_mode = 0;
}
}
/*
* 压缩数据块,可以多次调用
* 结束的时候,需要调用CompressBlockFinish处理尾部数据
*/
inline std::string CompressBlock(const std::string& src)
{
return CompressBlock(src.c_str(), src.size());
}
/*
* 压缩数据块,可以多次调用
* 结束的时候,需要调用CompressBlockFinish处理尾部数据
*/
std::string CompressBlock(const void* src, size_t srcLen)
{
if (src == NULL || srcLen == 0)
return {};
m_zlibStream.next_in = (Bytef*)src;
m_zlibStream.avail_in = (uint32_t)srcLen;
std::string ret;
do {
m_zlibStream.avail_out = (uint32_t)m_nCacheSize;
m_zlibStream.next_out = (Bytef*)m_pCacheBuf;
m_nErrCode = deflate(&m_zlibStream, Z_NO_FLUSH);
if (m_nErrCode != Z_OK)
break;
ret.append(m_pCacheBuf, m_nCacheSize - m_zlibStream.avail_out);
} while (m_zlibStream.avail_out == 0);
return ret;
}
/*
* 完成压缩数据块
* 调用CompressBlock压缩数据完毕后,需要调用此方法,返回值也是内容的一部分
*/
std::string CompressBlockFinish()
{
if (m_nErrCode != Z_OK)
return {};
std::string ret;
do {
m_zlibStream.avail_out = (uint32_t)m_nCacheSize;
m_zlibStream.next_out = (Bytef*)m_pCacheBuf;
m_nErrCode = deflate(&m_zlibStream, Z_FINISH);
if (m_nErrCode != Z_STREAM_END && m_nErrCode != Z_OK)
break;
ret.append(m_pCacheBuf, m_nCacheSize - m_zlibStream.avail_out);
} while (m_zlibStream.avail_out == 0);
return ret;
}
/*
* 压缩数据,一次性传入所有数据,返回压缩后的数据,不需要调用CompressBlockFinish
*/
std::string Compress(const std::string& src)
{
return Compress(src.c_str(), src.size());
}
/*
* 压缩数据,一次性传入所有数据,返回压缩后的数据,不需要调用CompressBlockFinish
*/
std::string Compress(const void* src, size_t srcLen)
{
if (src == NULL || srcLen == 0)
return {};
std::string ret = CompressBlock(src, srcLen);
ret += CompressBlockFinish();
return ret;
}
/*
* 初始化解压控制器
* 不能同时初始化压缩和解压两个控制器
* windowBits:默认是MAX_WBITS + 32,能自动检测zlib和gzip两种格式。如果是deflate格式,需要传入-MAX_WBITS
*/
bool InitDecompress(int windowBits = MAX_WBITS + 32)
{
if (m_mode != 0)
return false;
if (inflateInit2(&m_zlibStream, windowBits) != Z_OK)
return false;
m_windowbits = windowBits;
m_mode = 2;
return true;
}
/*
* 销毁解压控制器
* 一般情况下不需要主动调用,除非是上一次操作结束了需要再次解压新数据,先End再次Init(不推荐)
*/
void DecompressEnd()
{
if (m_mode == 2)
{
inflateEnd(&m_zlibStream);
m_mode = 0;
}
}
/*
* 解压数据块,可以多次调用
*/
inline std::string Decompress(const std::string& src)
{
return Decompress(src.c_str(), src.size());
}
/*
* 解压数据块,可以多次调用
*/
std::string Decompress(const void* src, size_t srcLen)
{
if (src == NULL || srcLen == 0)
return {};
m_zlibStream.next_in = (Bytef*)src;
m_zlibStream.avail_in = (uint32_t)srcLen;
std::string ret;
do {
m_zlibStream.avail_out = (uint32_t)m_nCacheSize;
m_zlibStream.next_out = (Bytef*)m_pCacheBuf;
m_nErrCode = inflate(&m_zlibStream, Z_NO_FLUSH);
if (m_nErrCode != Z_STREAM_END && m_nErrCode != Z_OK)
break;
ret.append(m_pCacheBuf, m_nCacheSize - m_zlibStream.avail_out);
} while (m_zlibStream.avail_out == 0);
return ret;
}
private:
z_stream m_zlibStream{};
char *m_pCacheBuf{};
size_t m_nCacheSize;
bool m_bFreeCacheBuf{};
int m_nErrCode{};
int m_windowbits{};
int m_mode; //1-加密;2-解密
};
/*
void zlibhandlertest()
{
std::string str = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
for (int i = 0; i < 1024 * 1024; i++)
{
str.append(std::to_string(i));
}
char* pstr = strdup(str.c_str());
char* pstr2 = strdup(str.c_str());
ZlibHandler z1;
z1.InitCompress(-MAX_WBITS);
std::string compress1 = z1.Compress(str.c_str(), str.length());
ZlibHandler z2;
z2.InitCompress(-MAX_WBITS);
std::string compress2_1 = z2.CompressBlock(pstr, str.length());
free(pstr);
std::string compress2_2 = z2.CompressBlock(pstr2, str.length());
free(pstr2);
std::string compress2_3 = z2.CompressBlockFinish();
ZlibHandler de1;
de1.InitDecompress(-MAX_WBITS);
std::string decompress1 = de1.Decompress(compress1.c_str(), compress1.length());
if (decompress1 == str)
printf("check ok!\n");
ZlibHandler de2;
de2.InitDecompress(-MAX_WBITS);
std::string decompress2 = de2.Decompress(compress2_1 + compress2_2 + compress2_3);
if (decompress2 == str + str)
printf("check ok!\n");
ZlibHandler de3;
de3.InitDecompress(-MAX_WBITS);
std::string decompress3 = de3.Decompress(compress2_1);
decompress3 += de3.Decompress(compress2_2);
decompress3 += de3.Decompress(compress2_3);
if (decompress3 == str + str)
printf("check ok!\n");
}
*/