我已经从源代码安装了 libzip(如 install.md 中所述)并重新编写了您的源代码。我添加了一个文本文件(带有“Hello world”)和一个包含一个文本文件的 zip 文件。
我没有收到错误。(但是,zip 文件中没有添加任何内容,所以这也不正确)
(忽略注释掉的异常参数:P)
#include <zip.h>
#include <exception>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <string>
static constexpr auto add_file{"file.txt"};
static constexpr auto zip_file{"zipfile.zip"};
static constexpr auto AUTO_FREE_BUF{false}; //1-0
static constexpr auto ADD_FILE{true}; //1-0
class MsgException : public std::exception {
public:
MsgException(std::string message) : _message(message) {}
char const *what() const noexcept override { return _message.c_str(); }
private:
std::string const _message;
};
int main() {
std::cout << "Started main\n";
auto const sz = std::filesystem::file_size(zip_file);
auto *const buf = new char[sz];
{
std::ifstream ifs{zip_file, std::ios::binary};
ifs.read(buf, sz);
}
std::cout << "Zipfile read\n";
zip_error_t ze;
try {
zip_error_init(&ze);
auto *zs = zip_source_buffer_create(buf, sz, AUTO_FREE_BUF ? 1 : 0, &ze);
if (zs == nullptr) throw MsgException("Can't create source: %s." /*, zip_error_strerror(&ze)*/);
//zip_error_init(&ze);
auto *z = zip_open_from_source(zs, 0, &ze);
if (z == nullptr) throw MsgException("Can't open zip from source: %s." /*, zip_error_strerror(&ze)*/);
if (ADD_FILE) {
//add file
auto *file = zip_source_file(z, add_file, 0, -1);
if (file == nullptr) throw MsgException("Can't create data source from file '%s': %s." /*, add_file, zip_strerror(z)*/);
if (zip_file_add(z, add_file, file, ZIP_FL_ENC_GUESS) < 0) {
//? zip_source_free(file);
throw MsgException("Can't file to zip archive: %s." /*, zip_strerror(z)*/);
}
}
zip_source_keep(zs);
if (zip_close(z) < 0) throw MsgException("Can't close zip archive: %s." /*, zip_strerror(z)*/);
//write back archive to disk
//..
zip_source_free(zs); //<-is supposed to NOT free the buffer (with freep=0) but sometimes does
} catch (std::exception &e) {
std::cerr << "Program aborted with error: " << e.what() << '\n';
}
zip_error_fini(&ze);
if (!AUTO_FREE_BUF) delete[] buf;
std::cout << "Finished main\n";
return 0;
}
使用构建
g++ -std=c++17 main.cpp -lzip -o main
编辑:添加了一些 RAII
#include <zip.h>
#include <exception>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
static constexpr auto add_file{ "file.txt" };
static constexpr auto zip_file{ "zipfile.zip" };
static constexpr auto AUTO_FREE_BUF{ false }; //1-0
static constexpr auto ADD_FILE{ true }; //1-0
class MsgException : public std::exception {
public:
MsgException(std::string message) : _message(message) {}
char const* what() const noexcept override { return _message.c_str(); }
private:
std::string const _message;
};
//RAII
class ZipError {
public:
ZipError() { zip_error_init(&ze); }
~ZipError() { zip_error_fini(&ze); }
zip_error* operator&() { return &ze; }
// actually probably need to delete copy/move constructor/assignment etc...
private:
zip_error_t ze;
};
int main() {
std::cout << "Started main\n";
std::vector<char> buf(std::filesystem::file_size(zip_file)); // RAII
{
std::ifstream ifs{ zip_file, std::ios::binary };
ifs.read(buf.data(), buf.size());
}
std::cout << "Zipfile read\n";
try {
ZipError ze;
auto* zs = zip_source_buffer_create(buf.data(), buf.size(), AUTO_FREE_BUF ? 1 : 0, &ze);
if (zs == nullptr) throw MsgException("Can't create source: %s." /*, zip_error_strerror(&ze)*/);
//zip_error_init(&ze);
auto* z = zip_open_from_source(zs, 0, &ze);
if (z == nullptr) throw MsgException("Can't open zip from source: %s." /*, zip_error_strerror(&ze)*/);
if (ADD_FILE) {
//add file
auto* file = zip_source_file(z, add_file, 0, -1);
if (file == nullptr) throw MsgException("Can't create data source from file '%s': %s." /*, add_file, zip_strerror(z)*/);
if (zip_file_add(z, add_file, file, ZIP_FL_ENC_GUESS) < 0) {
//? zip_source_free(file);
throw MsgException("Can't file to zip archive: %s." /*, zip_strerror(z)*/);
}
}
zip_source_keep(zs);
if (zip_close(z) < 0) throw MsgException("Can't close zip archive: %s." /*, zip_strerror(z)*/);
//write back archive to disk
//..
zip_source_free(zs); //<-is supposed to NOT free the buffer (with freep=0) but sometimes does
}
catch (std::exception& e) {
std::cerr << "Program aborted with error: " << e.what() << '\n';
}
std::cout << "Finished main\n";
return 0;
}