如何正确使用zlib::inflate_stream::write?技术细节问询
zlib::inflate_stream::write 工作细节疑问
现有代码
zlib::z_params params; zlib::inflate_stream inflate; params.data_type = zlib::binary; params.avail_in = inBufferSize; params.next_in = inBuffer; params.avail_out = outBufferSize; params.next_out = outBuffer; boost::beast::error_code boostErrorCode; inflate.write(zParams, zlib::Flush::finish, boostErrorCode);
因输入常为分批数据但不愿修改zlib::Flush::finish参数,结合不同Flush取值,针对以下问题逐一解答:
1. 压缩数据以位存储,能否确保已使用输入字节的所有位都被解析,且next_out指向的字节未被使用?
zlib内部会精准处理压缩数据的位流,无论使用哪种Flush参数,只要输入的压缩数据格式合法,已消费的输入字节的所有位都会被完全解析,不会残留未处理的位。
next_out始终指向下一个未被写入的字节:所有已完成解压的字节都存放在next_out之前的内存区域,当前next_out指向的位置确实未被写入。若使用Flush::finish,会强制处理完所有输入位直到压缩流结束,此时若输入是完整的压缩流,avail_in会变为0,next_out停在所有解压数据写入后的下一个位置。
2. 若输入缓冲区包含压缩数据后接未压缩数据,zlib会识别并提前结束还是报错?
zlib的inflate仅处理符合zlib/gzip格式的压缩数据,当它解析到压缩流的结束标记(如zlib的ADLER32校验和、gzip的尾部校验信息)时,就会停止处理,不会触碰后续的未压缩数据,也不会报错。
- 使用
Flush::finish:会确保处理完整个合法压缩流后停止,未压缩数据会留在avail_in中,avail_in的值等于未压缩数据的长度。 - 使用
Flush::none/Flush::sync_flush:同样在压缩流结束后停止处理,后续未压缩数据不会被解析,仅保留在输入缓冲区中。只有当压缩流本身格式错误时,才会触发错误码。
3. 若输入缓冲区含两个独立压缩的数据块,zlib会区分并在第二个块前停止还是全部解压?
需分两种情况判断:
- 如果是同一个zlib/gzip流内的多个DEFLATE压缩块:zlib会将其视为单个连续流,无论使用哪种Flush参数,都会全部解压,直到整个流结束。
- 如果是两个完全独立的zlib/gzip流(如两个完整压缩文件拼接):zlib处理完第一个流后,会进入流结束状态(
Z_STREAM_END),不会自动处理第二个流。- 使用
Flush::finish:处理完第一个流后立即停止,第二个流的数据会留在avail_in中;若要处理第二个流,需先重置inflate_stream。 - 使用
Flush::none:当第一个流处理完毕后,inflate会返回流结束状态,后续调用write也不会处理第二个流,必须重置后才能继续解析。
- 使用
4. 若输入为分块数据,如何判断解压完成?
可通过以下两点判断:
- 检查inflate的状态与错误码:当inflate返回
Z_STREAM_END状态(对应boost封装的状态标识),且boostErrorCode无错误时,说明当前压缩流已处理完毕。 - 结合输入缓冲区的剩余量:若所有分块数据已全部输入,且
avail_in变为0,同时上述流结束状态触发,即可确认解压完成。
不同Flush参数的影响:
- 使用
Flush::finish:会强制将当前输入的压缩流处理至结束,一旦触发流结束状态,即可判定解压完成;若输入分块中包含后续非压缩数据,avail_in会有剩余,但不影响流结束状态的判定。 - 使用
Flush::none/Flush::sync_flush:需持续输入分块数据,直到触发流结束状态,且所有输入分块已被完全消费(avail_in为0),才能确认解压完成;若中途使用sync_flush,会输出当前已解压的数据,但不会触发流结束状态,需继续输入后续分块。
内容的提问来源于stack exchange,提问作者Nadav Shragai
相关产品推荐
相关产品推荐

