You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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存在缺陷。

解决方法

  1. 合并原始数据后再压缩:先把string_data_1和string_data_2合并成一个字符串,再用Zlib RAW模式压缩,这样解压时一次就能得到全部内容。
  2. 分两次解压:保留分别压缩的逻辑,解压时先处理第一段压缩数据,再处理第二段,最后合并解压结果。

内容的提问来源于stack exchange,提问作者Serg_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 11:45:32