C++ minizip的简单使用,zip文件的创建、读取、修改、密码压缩、4G以上大文件压缩。

服务器 0

        兄弟姐妹们好,深夜党又来记录枯燥的编程生活了。今天给大家带来的是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的文件及其功能如下:

  1. minizip.h: 主要的头文件,包含了minizip的所有接口和定义.
  2. unzip.h: 提供了对ZIP文件的解压缩支持.
  3. zip.h: 提供了对ZIP文件的创建和修改支持.
  4. ioapi.h: 提供了对文件读写的支持.
  5. ioapi.c: 文件读写的实现.
  6. unzip.c: 文件解压缩的实现.
  7. zip.c: 文件压缩的实现.

        这些文件组合在一起,提供了minizip的所有功能。

        对于每个文件,其实还有更详细的信息,但是大体上,minizip.h 是整个库的主要接口,unzip.h 和 zip.h 分别提供了解压缩和压缩的接口,ioapi.h 和 ioapi.c 提供了文件读写的接口和实现,unzip.c 和 zip.c 分别提供了解压缩和压缩的实现。

        总的来说,minizip提供了一系列的接口,便于开发者更方便的操作压缩文件。

        minizip的功能:

  1. ZIP文件的创建: 可以在已有文件或者新建文件中加入其他文件并进行压缩。
  2. ZIP文件的读取: 可以读取ZIP文件中的文件并解压缩。
  3. ZIP文件的修改: 可以修改ZIP文件中的文件,添加,删除或更新文件。
  4. 支持密码压缩: 可以在压缩过程中使用密码保护压缩文件。
  5. 支持大文件: 支持压缩和解压缩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,自己还需要消化消化,好梦。

也许您对下面的内容还感兴趣: