忙忙碌碌,更新不及时诶。
C/C++代码

zlib封装C++类


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");
}
*/


blackfeather 2025/6/25 0评论