#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <stdexcept>
#include <fstream>
#include "zip.h" // 假设使用minizip库
class ZipWriter {
private:
// ZIP文件指针包装器,用于自动管理资源
struct ZipDeleter {
void operator()(zipFile* zf) const {
if (zf && *zf) {
zipClose(*zf, nullptr);
}
}
};
std::unique_ptr<zipFile, ZipDeleter> zipWrapper_;
int compressionLevel_;
std::string filename_;
public:
// 构造函数
ZipWriter(const std::string& filename, int compressionLevel = 4)
: filename_(filename), compressionLevel_(compressionLevel) {
// 初始化ZIP文件
zipFile zf = zipOpen(filename_.c_str(), APPEND_STATUS_CREATE);
if (!zf) {
throw std::runtime_error("无法创建ZIP文件: " + filename_);
}
// 用unique_ptr管理资源
zipWrapper_ = std::unique_ptr<zipFile, ZipDeleter>(new zipFile(zf));
}
// 添加二进制文件到ZIP
void addBinaryFile(const std::string& zipPath, const std::vector<uint8_t>& data) {
if (!zipWrapper_ || !*zipWrapper_) {
throw std::runtime_error("ZIP文件未初始化");
}
zip_fileinfo zi = {0};
// 打开ZIP中的新文件
int err = zipOpenNewFileInZip(*zipWrapper_, zipPath.c_str(),
&zi, nullptr, 0, nullptr, 0, nullptr,
Z_DEFLATED, compressionLevel_);
if (err != ZIP_OK) {
throw std::runtime_error("无法在ZIP中创建文件: " + zipPath);
}
// 写入二进制数据
err = zipWriteInFileInZip(*zipWrapper_, data.data(), static_cast<unsigned int>(data.size()));
if (err != ZIP_OK) {
zipCloseFileInZip(*zipWrapper_);
throw std::runtime_error("写入ZIP文件失败: " + zipPath);
}
// 关闭ZIP中的文件
zipCloseFileInZip(*zipWrapper_);
}
// 添加文本文件到ZIP
void addTextFile(const std::string& zipPath, const std::string& content) {
// 将文本转换为二进制数据
std::vector<uint8_t> data(content.begin(), content.end());
addBinaryFile(zipPath, data);
}
// 从文件系统添加文件到ZIP(二进制方式)
void addFileFromDisk(const std::string& zipPath, const std::string& diskPath) {
// 读取磁盘文件
std::ifstream file(diskPath, std::ios::binary | std::ios::ate);
if (!file.is_open()) {
throw std::runtime_error("无法打开文件: " + diskPath);
}
std::streamsize size = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<uint8_t> buffer(size);
if (!file.read(reinterpret_cast<char*>(buffer.data()), size)) {
throw std::runtime_error("读取文件失败: " + diskPath);
}
// 添加到ZIP
addBinaryFile(zipPath, buffer);
}
// 显式关闭ZIP文件(通常不需要手动调用,析构函数会处理)
void close() {
zipWrapper_.reset();
}
// 析构函数
~ZipWriter() {
if (zipWrapper_ && *zipWrapper_) {
close();
}
}
// 禁用拷贝构造和赋值
ZipWriter(const ZipWriter&) = delete;
ZipWriter& operator=(const ZipWriter&) = delete;
};
int main() {
try {
// 创建ZIP写入器
ZipWriter writer("example.zip");
// 添加文本文件
writer.addTextFile("readme.txt", "这是一个示例文本文件");
// 添加二进制文件
std::vector<uint8_t> binaryData = {0x48, 0x65, 0x6C, 0x6C, 0x6F};
writer.addBinaryFile("data.bin", binaryData);
// 从磁盘添加文件
writer.addFileFromDisk("disk/zipwriter.cpp","zipwriter.cpp");
// 自动关闭(析构函数处理)
} catch (const std::exception& e) {
std::cerr << "错误: " << e.what() << std::endl;
return 1;
}
return 0;
}
把上述代码保存为zipwriter.cpp,然后编译执行,并用unzip工具观察生成的文件
g++ zipwriter.cpp -o zipwt /par/zlib-1.3.1/contrib/minizip/zip.c /par/zlib-1.3.1/contrib/minizip/ioapi.c -L /par/zlib-1.3.1 -I /par/zlib-1.3.1/ -I /par/zlib-1.3.1/contrib/minizip /par/zlib-1.3.1/libz.a -Wno-register -Wno-cast-qual
./zipwt
unzip -l example.zip
Archive: example.zip
Length Date Time Name
--------- ---------- ----- ----
30 1980-01-00 00:00 readme.txt
5 1980-01-00 00:00 data.bin
4121 1980-01-00 00:00 disk/zipwriter.cpp
--------- -------
4156 3 files
另外注意,由于g++编译器比gcc更加严格,需要修改上述zip.c中的一行才能通过编译
//zi->ci.crc32 = crc32(zi->ci.crc32,buf,(uInt)len);
// 修改后:
zi->ci.crc32 = crc32(zi->ci.crc32, (const Bytef*)buf, (uInt)len);