使用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
相关产品推荐
相关产品推荐

