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

使用libzip从缓冲区向ZIP归档添加多文件时内容乱码求助

问题描述

我基于libzip示例库中的in-memory.c修改代码,尝试将多个数据块归档到ZIP的不同文件中。目前ZIP文件能正常保存,也包含指定的文件,但每个文件的内容都是乱码。相关代码如下,求技术支持:

bool push_files(zip_t* za) {
  for (int i = 0; i < 10; i++) {
    // Generate data
    std::stringstream ss;
    ss << "Test file #" << i;
    std::string a = ss.str();

    zip_source_t* source = zip_source_buffer(za, a.c_str(), a.size(), 0);

    if (source == NULL) {
      std::cerr << "error creating source: " << zip_strerror(za) << std::endl;
      return false;
    }

    // Add buffer with filename
    std::stringstream fname;
    fname << "TEST-" << i;
    a = fname.str();

    if (zip_file_add(za, a.c_str(), source, ZIP_FL_ENC_UTF_8) < 0) {
      std::cerr << "error adding source: " << zip_strerror(za) << std::endl;
      return false;
    }
  }
  return true;
}

int main() {
  zip_source_t* src;
  zip_error_t error;
  zip_t* za;

  zip_error_init(&error);

  if ((src = zip_source_buffer_create(NULL, 0, 1, &error)) == NULL) {
    std::cerr << "can't create source: " << zip_error_strerror(&error) << std::endl;
    zip_error_fini(&error);
    return 1;
  }

  if ((za = zip_open_from_source(src, ZIP_TRUNCATE, &error)) == NULL) {
    std::cerr << "can't open zip from source: " << zip_error_strerror(&error) << std::endl;
    zip_source_free(src);
    zip_error_fini(&error);
    return 1;
  }

  zip_error_fini(&error);

  zip_source_keep(src);

  if (!push_files(za))
    return -1;

  if (zip_close(za) < 0) {
    std::cerr << "can't close zip archive" << zip_strerror(za) << std::endl;
    return 1;
  }

  // ... omissis, save archive to file as in in-memory.c
}
问题分析与解决

乱码的核心原因是你在创建zip_source_buffer后,复用了字符串变量a覆盖了原数据的内存。

zip_source_buffer的最后一个参数传的是0,意味着它不会复制传入的缓冲区数据,而是直接引用原内存地址。当你执行a = fname.str();时,原字符串a的内容被覆盖,原内存的数据发生变化,导致libzip写入ZIP的内容变成新的文件名数据(或是内存被覆盖后的垃圾值)。

修复方法有两种:

  • 方法一:修改zip_source_buffer的最后一个参数为1,让libzip复制缓冲区数据,这样原内存后续修改不会影响归档内容:
    zip_source_t* source = zip_source_buffer(za, a.c_str(), a.size(), 1);
    
  • 方法二:避免复用原字符串变量,为文件名创建独立的字符串对象,确保原数据内存直到文件添加完成前都不被修改:
    // Generate data
    std::stringstream ss;
    ss << "Test file #" << i;
    std::string content = ss.str(); // 用单独变量存内容
    
    zip_source_t* source = zip_source_buffer(za, content.c_str(), content.size(), 0);
    
    // ...
    
    // Add buffer with filename
    std::stringstream fname;
    fname << "TEST-" << i;
    std::string filename = fname.str(); // 单独变量存文件名
    
    if (zip_file_add(za, filename.c_str(), source, ZIP_FL_ENC_UTF_8) < 0) {
      std::cerr << "error adding source: " << zip_strerror(za) << std::endl;
      zip_source_free(source); // 失败时释放资源,避免内存泄漏
      return false;
    }
    

另外补充:在zip_file_add失败时,记得调用zip_source_free(source)释放资源,否则会造成内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 15:00:18