0

0

c++怎么使用zlib压缩解压数据_c++ 字节流压缩算法与内存操作【实战】

穿越時空

穿越時空

发布时间:2026-01-07 18:38:30

|

608人浏览过

|

来源于php中文网

原创

zlib压缩内存数据应先确认compress()和uncompress()的边界条件;二者是最轻量接口,适用于小数据量。

c++怎么使用zlib压缩解压数据_c++ 字节流压缩算法与内存操作【实战】

zlib 压缩内存数据:先确认 compress()uncompress() 的边界条件

这两个函数是 zlib 最轻量的内存压缩接口,适合小数据量(解压。它们不支持流式处理,也不自动管理内存——你必须提前分配好输出缓冲区,并传入其大小指针。

常见错误是传入的 destLen 指针未初始化,或指向的值小于实际所需空间,导致返回 Z_BUF_ERROR;更隐蔽的问题是:解压时若输入数据被截断或损坏,uncompress() 可能静默返回 Z_DATA_ERROR 而不抛异常,容易被忽略。

  • compress() 要求目标缓冲区大小至少为 compressBound(srcLen) 返回值,不能凭经验估算
  • 解压前务必检查原始压缩数据长度是否 ≥ 4 字节(zlib header 最小长度),否则直接跳过调用
  • 返回值必须显式判断:Z_OK 才代表成功;Z_MEM_ERROR 表示堆内存不足(少见但可能发生在嵌入式环境)
uLong destLen = compressBound(srcLen);
Bytef* dest = new Bytef[destLen];
int ret = compress(dest, &destLen, src, srcLen);
if (ret != Z_OK) {
    // 处理错误,不要假设 destLen 仍有效
}
// 注意:destLen 此时已被写入真实压缩后长度

z_stream 手动管理流式压缩:避免 deflateInit() 后忘记 deflateEnd()

当需要分块压缩、控制压缩级别、或复用压缩上下文时,必须使用 z_stream 结构体 + deflate* 系列函数。这是生产环境更可控的方式,但生命周期管理极易出错。

最常踩的坑是:在 deflateInit() 成功后,因异常提前退出而未调用 deflateEnd(),导致 zlib 内部分配的内存泄漏(尤其在循环中反复创建时);另一个是误将 z_stream变量传递给异步回调,而回调执行时该变量已析构。

立即学习C++免费学习笔记(深入)”;

ColorMagic
ColorMagic

AI调色板生成工具

下载
  • deflateInit2() 第二个参数可设压缩级别(Z_DEFAULT_COMPRESSION 或 -1~9),负值启用 gzip header(即生成 .gz 兼容格式)
  • 每次调用 deflate() 前,必须设置 strm->next_instrm->avail_instrm->next_outstrm->avail_out,且不能重叠
  • 压缩结束需调用 deflate(strm, Z_FINISH),并循环直到返回 Z_STREAM_END,否则输出不完整
z_stream strm;
strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL;
int ret = deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, 15+16, 8, Z_DEFAULT_STRATEGY);
if (ret != Z_OK) return ret;
<p>strm.next_in = const_cast<Bytef*>(src);
strm.avail_in = srcLen;
strm.next_out = dest;
strm.avail_out = destSize;</p><p>while (strm.avail_in > 0) {
ret = deflate(&strm, Z_NO_FLUSH);
if (ret != Z_OK) break;
}
ret = deflate(&strm, Z_FINISH); // 必须收尾
deflateEnd(&strm); // 必须释放

解压时识别输入格式:gzip、zlib、raw deflate 三者不能混用

zlib 库默认按「zlib 格式」解压(RFC1950),但网络传输或文件读取的数据可能是 gzip(RFC1952)或 raw deflate(RFC1951)。若格式不匹配,inflate() 会立即返回 Z_DATA_ERROR,而不是尝试自动探测。

关键区别在头部字节:zlib 以 0x78 开头(常见 0x78 0x01, 0x78 0x9C);gzip 以 0x1F 0x8B 开头;raw deflate 无标准 header。强行用 zlib 模式解 gzip 数据,前两个字节就会校验失败。

  • 解压前可用前两字节快速判断:if (data[0] == 0x1F && data[1] == 0x8B) → 用 inflateInit2(&strm, 16+MAX_WBITS)
  • 若确定是 raw deflate(如某些协议自定义封装),用 inflateInit2(&strm, -MAX_WBITS)(负窗口位数)
  • 永远不要依赖 inflate() 自动识别格式——它不会

C++ RAII 封装要点:别让 z_stream 的手动管理污染业务逻辑

裸用 z_stream 容易漏掉 deflateEnd()/inflateEnd(),也难统一错误处理。用 RAII 封装是必要选择,但要注意几个细节:

  • 移动构造/赋值必须置空源对象的 strm->opaque,否则双重 deflateEnd() 会 crash
  • 不要在构造函数里调用 deflateInit2() 并吞掉错误——应让调用方感知初始化失败
  • 压缩/解压方法应返回 std::pair<int size_t></int>:前者是 zlib 错误码,后者是本次处理的有效字节数,方便上层做流控
  • 避免在析构函数里抛异常(deflateEnd() 理论上也可能失败),一律用返回值或日志

真正容易被忽略的是:zlib 的压缩率和速度高度依赖数据特征。对已经加密或随机性高的内存块(如 AES 加密后的密文),zlib 压缩率趋近于 0,甚至膨胀。上线前务必用真实数据样本跑压测,而不是只测文本或图片。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

846

2023.08.22

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

490

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

202

2025.07.04

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1010

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

611

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

334

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

235

2025.08.29

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1923

2023.10.19

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

3

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
CSS3 教程
CSS3 教程

共18课时 | 7万人学习

Sass 教程
Sass 教程

共14课时 | 0.9万人学习

Pandas 教程
Pandas 教程

共15课时 | 1.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号