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评论