兄弟姐妹们好,深夜党又来记录枯燥的编程生活了。今天给大家带来的是minizip库,一个解压和压缩文件的开源代码库,如题目所示的结构来介绍。你可以在下面的链接搜索到minizip库:
http://www.winimage.com/zLibDll/minizip.html
github地址:
zlib/contrib/minizip at master · madler/zlib · GitHub
请注意minizip库是在zlib上开发的,也就是minizip基于zlib向上封了一层,给出好多复杂的实现来方便我们。所以minizip需要依赖zipstate.lib库,这个是zlib编出来的lib,所以想用minizip还有点复杂呢。另外,无论是zlib还是minizip都是C语言写出来的,代码看起来工整简洁。
目录
一、minizip文件结构及其功能
二、ZIP文件的创建
三、zip文件的读取
四、zip文件的修改
五、密码压缩4GB以上的文件
六、总结
一、minizip文件结构及其功能
minizip的文件及其功能如下:
- minizip.h: 主要的头文件,包含了minizip的所有接口和定义.
- unzip.h: 提供了对ZIP文件的解压缩支持.
- zip.h: 提供了对ZIP文件的创建和修改支持.
- ioapi.h: 提供了对文件读写的支持.
- ioapi.c: 文件读写的实现.
- unzip.c: 文件解压缩的实现.
- zip.c: 文件压缩的实现.
这些文件组合在一起,提供了minizip的所有功能。
对于每个文件,其实还有更详细的信息,但是大体上,minizip.h 是整个库的主要接口,unzip.h 和 zip.h 分别提供了解压缩和压缩的接口,ioapi.h 和 ioapi.c 提供了文件读写的接口和实现,unzip.c 和 zip.c 分别提供了解压缩和压缩的实现。
总的来说,minizip提供了一系列的接口,便于开发者更方便的操作压缩文件。
minizip的功能:
- ZIP文件的创建: 可以在已有文件或者新建文件中加入其他文件并进行压缩。
- ZIP文件的读取: 可以读取ZIP文件中的文件并解压缩。
- ZIP文件的修改: 可以修改ZIP文件中的文件,添加,删除或更新文件。
- 支持密码压缩: 可以在压缩过程中使用密码保护压缩文件。
- 支持大文件: 支持压缩和解压缩4G以上的文件。
二、ZIP文件的创建
这是一个使用 minizip 库在 C++ 中创建 Zip 文件的示例代码:
#include <iostream>#include "minizip/zip.h"int main(){ // 文件名 const char *zipfile = "example.zip"; // 需要压缩的文件 const char *file = "example.txt"; zipFile zf = zipOpen(zipfile, APPEND_STATUS_CREATE); if(zf == NULL) { std::cerr << "Error creating " << zipfile << std::endl; return 1; } // 压缩文件 int err = zipOpenNewFileInZip(zf, file, NULL, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_BEST_COMPRESSION); if(err != ZIP_OK) { std::cerr << "Error adding " << file << " to " << zipfile << std::endl; return 1; } // 读取文件并压缩 FILE *f = fopen(file, "rb"); char buf[1024]; int len; while((len = fread(buf, 1, sizeof(buf), f)) > 0) { zipWriteInFileInZip(zf, buf, len); } fclose(f); zipCloseFileInZip(zf); zipClose(zf, NULL); std::cout << "Successfully created " << zipfile << std::endl; return 0;}
zipOpen,zipOpenNewFileInZip,zipWriteInFileInZip,zipCloseFileInZip和zipClose函数。zipOpen函数用来打开一个Zip文件或者创建一个新的Zip文件,zipOpenNewFileInZip用来在Zip文件中添加一个新文件,zipWriteInFileInZip用来向Zip文件中写入数据,zipCloseFileInZip用来关闭当前文件,zipClose用来关闭整个Zip文件。
这段代码中使用了 minizip 库中的一些函数来完成创建 Zip 文件的操作。
zipOpen
: 这个函数用来打开一个 Zip 文件或者创建一个新的 Zip 文件。这里使用了APPEND_STATUS_CREATE
参数来创建一个新的 Zip 文件,如果文件已经存在,则会覆盖原有的文件。zipOpenNewFileInZip
: 这个函数用来在 Zip 文件中添加一个新的文件。这里将要压缩的文件名传入函数。这个函数还有很多其他参数可以使用,如密码保护,设置文件时间等。zipWriteInFileInZip
: 这个函数用来向 Zip 文件中写入数据。这里使用了一个 while 循环读取文件中的数据,并将其写入 Zip 文件中。zipCloseFileInZip
: 这个函数用来关闭当前文件,表示写入操作完成。zipClose
: 这个函数用来关闭整个 Zip 文件,并将数据写入磁盘。
三、zip文件的读取
使用 minizip 库在 C++ 中读取 Zip 文件的示例代码:
#include <iostream>#include <string>#include <vector>#include "minizip/unzip.h"int main(){ // Zip 文件名 const char *zipfile = "example.zip"; // 需要读取的文件 const char *file = "example.txt"; unzFile uf = unzOpen(zipfile); if(uf == NULL) { std::cerr << "Error opening " << zipfile << std::endl; return 1; } // 打开文件 int err = unzLocateFile(uf, file, 0); if(err != UNZ_OK) { std::cerr << "Error locating " << file << " in " << zipfile << std::endl; unzClose(uf); return 1; } unz_file_info file_info; char filename[512]; err = unzGetCurrentFileInfo(uf, &file_info, filename, sizeof(filename), NULL, 0, NULL, 0); if(err != UNZ_OK) { std::cerr << "Error getting file info for " << file << std::endl; unzClose(uf); return 1; } // 打开文件 err = unzOpenCurrentFile(uf); if(err != UNZ_OK) { std::cerr << "Error opening " << file << std::endl; unzClose(uf); return 1; } // 读取文件 std::vector<char> buf(file_info.uncompressed_size); int len = unzReadCurrentFile(uf, &buf[0], buf.size()); if(len < 0) { std::cerr << "Error reading " << file << std::endl; unzCloseCurrentFile(uf); unzClose(uf); return 1; } // 关闭文件 unzCloseCurrentFile(uf); unzClose(uf); // 输出文件 std::cout << "Content of " << file << ":" << std::endl; std::cout.write(&buf[0], len); std::cout << std::endl; return 0;}
这段代码中使用了 minizip 库中的 unzOpen, unzLocateFile, unzGetCurrentFileInfo, unzOpenCurrentFile, unzReadCurrentFile, unzCloseCurrentFile 和 unzClose 函数。
unzOpen
: 这个函数用来打开一个 Zip文件。这里传入了需要读取的 Zip 文件名。unzLocateFile
: 这个函数用来定位文件在 Zip 文件中的位置。这里传入了需要读取的文件名。unzGetCurrentFileInfo
: 这个函数用来获取当前文件的信息,如文件名,文件大小等。unzOpenCurrentFile
: 这个函数用来打开当前文件,准备读取数据。unzReadCurrentFile
: 这个函数用来读取文件中的数据,并将其存入 buffer 中。unzCloseCurrentFile
: 这个函数用来关闭当前文件。unzClose
: 这个函数用来关闭整个 Zip 文件。
总的来说,这段代码实现了读取一个ZIP文件中的某个文件的功能,并且将读取到的文件内容输出到屏幕上。
四、zip文件的修改
修改 Zip 文件是一个比较复杂的操作,因为需要先把整个 Zip 文件解压缩出来,然后修改需要修改的文件,最后重新压缩成一个新的 Zip 文件。
#include <iostream>#include <fstream>#include "minizip/unzip.h"#include "minizip/zip.h"int main(){ // 输入的 Zip 文件 const char *zipfile = "example.zip"; // 要修改的文件 const char *file = "example.txt"; // 替换文件的路径 const char *replace_file = "new_example.txt"; // 输出的新的 Zip 文件 const char *new_zipfile = "new_example.zip"; unzFile uf = unzOpen(zipfile); if(uf == NULL) { std::cerr << "Error opening " << zipfile << std::endl; return 1; } zipFile zf = zipOpen(new_zipfile, APPEND_STATUS_CREATE); if(zf == NULL) { std::cerr << "Error creating " << new_zipfile << std::endl; unzClose(uf); return 1; } int err = unzGoToFirstFile(uf); while(err == UNZ_OK) { unz_file_info file_info; char filename[512]; err = unzGetCurrentFileInfo(uf, &file_info, filename, sizeof(filename), NULL, 0, NULL, 0); if(err != UNZ_OK) { std::cerr << "Error getting file info" << std::endl; unzClose(uf); zipClose(zf, NULL); return 1; } if( std::string(filename) == file) { // 打开替换文件 std::ifstream replace_stream(replace_file, std::ios::binary); if(!replace_stream.is_open()) { std::cerr << "Error opening " << replace_file << std::endl; unzClose(uf); zipClose(zf, NULL); return 1; } // 读取替换文件的数据 std::vector<char> buf((std::istreambuf_iterator<char>(replace_stream)), std::istreambuf_iterator<char>()); // 添加新文件到输出的 Zip 文件中 err = zipOpenNewFileInZip(zf, file, &file_info, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION); if(err != UNZ_OK) { std::cerr << "Error adding file to " << new_zipfile << std::endl; unzClose(uf); zipClose(zf, NULL); return 1; } err = zipWriteInFileInZip(zf, &buf[0], buf.size()); if(err != UNZ_OK) { std::cerr << "Error writing to " << new_zipfile << std::endl; unzClose(uf);zipClose(zf, NULL);return 1;}Copy code err = zipCloseFileInZip(zf); if(err != UNZ_OK) { std::cerr << "Error closing " << new_zipfile << std::endl; unzClose(uf); zipClose(zf, NULL); return 1; } } else { // 如果不是要修改的文件,则复制到输出的 Zip 文件中 err = unzOpenCurrentFile(uf); if(err != UNZ_OK) { std::cerr << "Error opening " << filename << std::endl; unzClose(uf); zipClose(zf, NULL); return 1; } // 添加新文件到输出的 Zip 文件中 err = zipOpenNewFileInZip(zf, filename, &file_info, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION); if(err != UNZ_OK) { std::cerr << "Error adding file to " << new_zipfile << std::endl; unzClose(uf); zipClose(zf, NULL); return 1; } // 读取文件并复制到输出的 Zip 文件中 std::vector<char> buf(file_info.uncomp err = zipCloseFileInZip(zf); if(err != UNZ_OK) { std::cerr << "Error closing " << new_zipfile << std::endl; unzClose(uf); zipClose(zf, NULL); return 1; } } else { // 如果不是要修改的文件,则复制到输出的 Zip 文件中 err = unzOpenCurrentFile(uf); if(err != UNZ_OK) { std::cerr << "Error opening " << filename << std::endl; unzClose(uf); zipClose(zf, NULL); return 1; } // 添加新文件到输出的 Zip 文件中 err = zipOpenNewFileInZip(zf, filename, &file_info, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION); if(err != UNZ_OK) { std::cerr << "Error adding file to " << new_zipfile << std::endl; unzClose(uf); zipClose(zf, NULL); return 1; } // 读取文件并复制到输出的 Zip 文件中 std::vector<char> buf(file_info.uncompressed_size); int len = unzReadCurrentFile(uf, &buf[0], buf.size()); if(len < 0) { std::cerr << "Error reading " << filename << std::endl; unzCloseCurrentFile(uf); unzClose(uf); zipClose(zf, NULL); return 1; } err = zipWriteInFileInZip(zf, &buf[0], buf.size()); if(err != UNZ_OK) { std::cerr << "Error writing to " << new_zipfile << std::endl; unzClose(uf); zipClose(zf, NULL); return 1; } err = zipCloseFileInZip(zf); if(err != UNZ_OK) { std::cerr << "Error closing " << new_zipfile << std::endl; unzClose(uf); zipClose(zf, NULL); return 1; } err = unzCloseCurrentFile(uf); if(err != UNZ_OK) { std::cerr << "Error closing " << filename << std::endl; unzClose(uf); zipClose(zf, NULL); return 1; } } err = unzGoToNextFile(uf); } // 关闭 unzClose(uf);// 关闭输出的 Zip 文件 err = zipClose(zf, NULL); if(err != UNZ_OK) { std::cerr << "Error closing " << new_zipfile << std::endl; return 1; } std::cout << "Successfully replaced " << file << " in " << zipfile << " with " << replace_file << std::endl; return 0;}
上面的代码简化了没有必要的注释和错误处理,但是其基本思路与之前提到的是相同的,它打开了输入的zip文件,并创建了输出的zip文件,遍历了输入文件中的所有文件,如果当前文件是要修改的文件,它会读取替换文件的内容并将其写入到输出文件中,如果不是要修改的文件,它会将其复制到输出文件中。
五、密码压缩4GB以上的文件
代码:
#include <iostream>#include <fstream>#include "minizip/zip.h"int main(){ // 输入文件路径 const char *input_file = "large_file.bin"; // 输出的 Zip 文件 const char *zipfile = "large_file.zip"; // 压缩密码 const char *password = "my_secret_password"; zipFile zf = zipOpen(zipfile, APPEND_STATUS_CREATE); if(zf == NULL) { std::cerr << "Error creating " << zipfile << std::endl; return 1; } // 打开输入文件 std::ifstream input_stream(input_file, std::ios::binary); if(!input_stream.is_open()) { std::cerr << "Error opening " << input_file << std::endl; zipClose(zf, NULL); return 1; } // 获取文件大小 input_stream.seekg(0, std::ios::end); std::streampos file_size = input_stream.tellg(); input_stream.seekg(0, std::ios::beg); // 设置文件信息 zip_fileinfo file_info = {}; get_filetime(input_file, &file_info.tmz_date, &file_info.dosDate); // 添加文件到 Zip 文件中 int err = zipOpenNewFileInZip3(zf, input_file, &file_info, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_BEST_COMPRESSION, 0, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, password, strlen(password)); if(err != ZIP_OK) { std::cerr << "Error adding file to " << zipfile << std::endl; zipClose(zf, NULL); return 1; } // 分块读取文件并写入 Zip 文件中 constexpr int buffer_size = 1024 * 1024; // 1MB std::vector<char> buffer(buffer_size); while(file_size > 0) { int read_size = std::min(file_size, (std::streampos)buffer_size); input_stream.read(&buffer[0], read_size); err = zipWriteInFileInZip(zf, &buffer[0], read_size); if(err != ZIP_OK) { std::cerr << "Error writing to " << zipfile << std::endl; zipClose(zf, NULL); return 1; } file_size -= read_size; } // 关闭文件 input_stream.close(); err = zipCloseFileInZip(zf); if(err != ZIP_OK) { std::cerr << "Error closing file in " << zipfile << std::endl; zipClose(zf, NULL); return 1; } err = zipClose(zf, NULL); if(err != ZIP_OK) { std::cerr << "Error closing " << zipfile << std::endl; return 1; } std::cout << "Successfully compressed " << input_file << " to " << zipfile << " with password " << password << std::endl; return 0;}
上面的代码使用 minizip 库来压缩一个 4GB 以上的文件,并且使用密码加密压缩的文件。它打开输入文件,并创建输出的 zip 文件,读取输入文件的数据并分块写入到输出的 zip 文件中。它使用 zipOpenNewFileInZip3 函数来添加文件并设置压缩密码,在文件写入完成后,关闭 zip 文件并输出成功消息。需要注意的是, 4GB以上的文件压缩可能需要很长时间, 并且需要很大的内存空间。
六、总结
以上代码来自github,自己还需要消化消化,好梦。