为何Zlib解压合并的RAW压缩数据仅解析第一部分?是Bug还是用法错误?
Zlib RAW模式合并压缩数据解压异常问题解答
问题描述
分别用Zlib RAW模式压缩两个字符串,合并压缩数据后执行解压,仅能得到第一部分数据,第二部分无法解压;但相同操作在Zstandard库中可正常解压全部数据。操作步骤如下:
- 准备两个待压缩字符串
string_data_1和string_data_2,用Zlib RAW模式分别压缩; - 合并两段压缩数据为一个字符串;
- 解压合并后的压缩数据时,仅得到第一部分内容。
示例代码:
#include <iostream> #include <string> #include <zlib.h> int my_Zlib__compress__RAW(std::string& string_data_to_be_compressed, std::string& string_compressed_result, int level_compressed) { uLong zlib_uLong = compressBound(string_data_to_be_compressed.size()); string_compressed_result.resize(zlib_uLong); // 使用deflateInit2(windowBits=-15)实现RAW模式压缩的自定义compress2 int status = my_compress2((Bytef*)&string_compressed_result[0], &zlib_uLong, (const Bytef*)&string_data_to_be_compressed[0], string_data_to_be_compressed.size(), level_compressed); if (status == Z_OK) { string_compressed_result.resize(zlib_uLong); return 0; } else { return 1; } } int my_Zlib__uncompress__RAW(std::string& string_data_to_be_uncompressed, std::string& string_compressed_data, size_t size_uncompressed_data) { string_data_to_be_uncompressed.resize(size_uncompressed_data); // 使用inflateInit2(windowBits=-15)实现RAW模式解压的自定义uncompress int status = my_uncompress((Bytef*)&string_data_to_be_uncompressed[0], (uLongf*)&size_uncompressed_data, (const Bytef*)&string_compressed_data[0], string_compressed_data.size()); if (status == Z_OK) { return 0; } } int main() { int level_compressed = 9; // 压缩第一段数据 std::string string_data_1 = "Hello12_Hello12_Hello125"; std::string string_compressed_result_RAW_1; int status = my_Zlib__compress__RAW(string_data_1 , string_compressed_result_RAW_1, level_compressed); // 压缩第二段数据 std::string string_data_2= "BUY22_BUY22_BUY223"; std::string string_compressed_result_RAW_2; status = my_Zlib__compress__RAW(string_data_2 , string_compressed_result_RAW_2, level_compressed); // 合并两段压缩数据 std::string Total_compressed_data = string_compressed_result_RAW_1 + string_compressed_result_RAW_2; // 解压合并后的数据 std::string string_uncompressed_result_RAW; int size_that_should_be_when_unpacking = string_data_1.size() + string_data_2.size(); status = my_Zlib__uncompress__RAW(string_uncompressed_result_RAW, Total_compressed_data, size_that_should_be_when_unpacking); std::cout<<string_uncompressed_result_RAW<<std::endl; // 仅输出Hello12_Hello12_Hello125 }
解答
这是对Zlib用法的误解,并非Zlib的Bug。
Zlib的uncompress函数(包括RAW模式下的实现)设计用于处理单个完整的压缩流。当你分别压缩两个字符串时,得到的是两个独立的、完整的DEFLATE压缩流(RAW模式即无zlib头/尾的纯DEFLATE流)。合并这两个流后,用一次uncompress解压时,Zlib在处理完第一个压缩流的结束标记后,就会停止解压,不会继续处理后续的第二个流——这是符合Zlib设计逻辑的正常表现。
而Zstandard库的解压逻辑允许连续处理多个独立的压缩帧,所以合并后能一次性解压全部内容,但这属于不同库的设计差异,并非Zlib存在缺陷。
解决方法
- 合并原始数据后再压缩:先把
string_data_1和string_data_2合并成一个字符串,再用Zlib RAW模式压缩,这样解压时一次就能得到全部内容。 - 分两次解压:保留分别压缩的逻辑,解压时先处理第一段压缩数据,再处理第二段,最后合并解压结果。
内容的提问来源于stack exchange,提问作者Serg_
相关产品推荐
相关产品推荐

