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

如何用zlib的deflate算法在内存中将缓冲区压缩至char数组?

实现zlib内存中压缩缓冲区到char数组

我明白你想要跳过文件IO,直接把zlib压缩的结果存到内存中的char数组里——这完全可行,只需要调整zlib的输出逻辑,用动态内存容器替代文件操作就行。下面是针对你的代码修改后的完整实现思路和代码:

核心修改点

  • 移除所有文件相关的操作(fopen/fwrite/fclose),改用**std::vector<char>**来动态存储压缩后的数据(它能自动扩容,避免固定数组大小不够的问题)。
  • 调整Write和Close方法,把原本写入文件的逻辑替换成向内存容器追加数据。
  • 补充必要的初始化逻辑,确保zlib流正确指向内存缓冲区。

首先更新类成员变量

在你的File类里,去掉文件指针m_pFile,添加一个动态内存容器来存压缩结果:

#include <vector>
// ...
class File {
private:
    z_stream m_Stream;
    bool m_bWrite;
    Bytef m_Buffer[4096]; // 推荐用4KB/8KB的缓冲区,zlib官方建议的大小
    std::vector<char> m_CompressedData; // 存储最终压缩结果
    // ... 其他成员
public:
    // 新增获取压缩数据的接口
    const char* GetCompressedData() const {
        return m_CompressedData.empty() ? nullptr : m_CompressedData.data();
    }
    size_t GetCompressedSize() const {
        return m_CompressedData.size();
    }
    // ... 其他方法
};

初始化压缩流(新增方法)

在开始压缩前,需要正确初始化zlib流和内存缓冲区:

bool File::OpenForCompression() {
    m_bWrite = true;
    memset(&m_Stream, 0, sizeof(m_Stream));
    // 初始化zlib压缩流,使用默认压缩级别
    int err = deflateInit(&m_Stream, Z_DEFAULT_COMPRESSION);
    if (err != Z_OK) {
        // 这里可以添加错误日志或处理逻辑
        return false;
    }
    // 绑定输出缓冲区到内存数组
    m_Stream.next_out = m_Buffer;
    m_Stream.avail_out = sizeof(m_Buffer);
    m_CompressedData.clear(); // 清空之前的数据
    return true;
}

修改Write方法(内存版)

把原本写入文件的逻辑改成向std::vector追加数据:

int File::Write(const void *pBuffer, int nByte) {
    if (!m_bWrite) return 0;

    m_Stream.next_in = (Bytef*)pBuffer;
    m_Stream.avail_in = (uInt)nByte;

    int err = deflate(&m_Stream, Z_NO_FLUSH);
    while (m_Stream.avail_out == 0) {
        // 把当前缓冲区的所有数据追加到内存容器
        m_CompressedData.insert(m_CompressedData.end(), 
                               reinterpret_cast<char*>(m_Buffer), 
                               reinterpret_cast<char*>(m_Buffer) + sizeof(m_Buffer));
        // 重置输出缓冲区,继续接收压缩数据
        m_Stream.avail_out = sizeof(m_Buffer);
        m_Stream.next_out = m_Buffer;
        err = deflate(&m_Stream, Z_NO_FLUSH);
        if (err != Z_OK) {
            // 压缩出错,返回0表示失败
            return 0;
        }
    }
    return nByte;
}

修改Close方法(完成压缩并收尾)

处理压缩流的收尾,把剩余的数据也存入内存容器:

bool File::Close() {
    if(m_bWrite) {
        int err;
        // 完成压缩流,写入所有剩余数据
        for (;;) {
            err = deflate(&m_Stream, Z_FINISH);
            // 计算缓冲区中已使用的字节数,追加到内存容器
            size_t usedBytes = sizeof(m_Buffer) - m_Stream.avail_out;
            if (usedBytes > 0) {
                m_CompressedData.insert(m_CompressedData.end(),
                                       reinterpret_cast<char*>(m_Buffer),
                                       reinterpret_cast<char*>(m_Buffer) + usedBytes);
            }
            if (err == Z_STREAM_END) break; // 压缩完成
            if (err != Z_OK) {
                CHECK_ERR(err, "deflate");
                deflateEnd(&m_Stream);
                return false;
            }
            // 重置缓冲区继续接收收尾数据
            m_Stream.avail_out = sizeof(m_Buffer);
            m_Stream.next_out = m_Buffer;
        }
        // 结束压缩流
        err = deflateEnd(&m_Stream);
        if (err != Z_OK) {
            CHECK_ERR(err, "deflateEnd");
            return false;
        }
        m_bWrite = false;
    } else {
        // 如果是解压模式,同样可以类似修改为内存解压,这里保留你的原逻辑(如果需要)
        int err = inflateEnd(&m_Stream);
        // 移除fclose,因为不再操作文件
        CHECK_ERR(err, "inflateEnd");
    }
    return true;
}

使用示例

File compFile;
if (compFile.OpenForCompression()) {
    const char* rawData = "你的原始缓冲区数据";
    int rawSize = strlen(rawData);
    compFile.Write(rawData, rawSize);
    compFile.Close();
    
    // 获取压缩后的数据和大小
    const char* compressed = compFile.GetCompressedData();
    size_t compressedSize = compFile.GetCompressedSize();
    
    // 这里就可以使用compressed指向的内存数组了
}

注意事项

  • 缓冲区m_Buffer的大小建议设置为4KB或8KB,这是zlib官方推荐的最优大小,能平衡内存占用和压缩效率。
  • 确保错误处理逻辑完善,zlib的每个操作都可能返回错误码,需要及时处理避免内存泄漏或数据丢失。
  • 如果需要兼容C风格的char数组,可以通过GetCompressedData()直接获取指针,或者把std::vector的数据复制到你自己的数组中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:54:22