Linux Minizip zlib 压缩文件或文件夹

最近项目需要用到压缩打包,为了方便能控制程序执行状态,不能够调用system,不能用tar zip等命令,在linux上只能找到zlib这一个库来做。以下是解决问题的过程:

1.下载zlib源码并编译安装,找到minizip的源码位置编译测试

    参考了如下网址:https://blog.csdn.net/whahu1989/article/details/80344373

2.阅读zlib的相关文档之后发现其只是对字符串进行了编码压缩,不满足直接打包压缩文件或文件夹的需求,需要对其进行封装,不过Minizip可以实现这个效果(不过还是要用到zlib的,因为minizip是基于zlib的)

    拷贝minizip文件夹中的相关源码到项目中来(ioapi.c,mztools.c,unzip.c,zip.c以及其头文件)

3.配置CMakelist

    (1)配置zlib

set(zlib_DIR /usr/local/lib/)
add_library(zlib SHARED IMPORTED)
set_target_properties(zlib PROPERTIES IMPORTED_LOCATION ${zlib_DIR}/libz.so)
target_link_libraries(project_name ${DIR_SRCS}  zlib)

      (2)配置minizip,将minizip文件夹中编译后的.o文件放到项目源代码目录中的lib目录(自己命名),.c文件放到main.cpp同级目录下

add_executable(project_name main.cpp ${CMAKE_CURRENT_LIST_DIR}/lib/ioapi.o ${CMAKE_CURRENT_LIST_DIR}/lib/zip.o ${CMAKE_CURRENT_LIST_DIR}/lib/unzip.o)

4.参考minizip.c在main.cpp编写代码

#include 
#include 
#include 
#include 

extern "C"
{
#include "zlib.h"
#include "include/zip.h"
#include "include/unzip.h"
}

void EnumDirFiles(const string& dirPrefix,const string& dirName,vector& vFiles)
{
    if (dirPrefix.empty() || dirName.empty())
        return;
    string dirNameTmp = dirName;
    string dirPre = dirPrefix;

    if (dirNameTmp.find_last_of("/") != dirNameTmp.length() - 1)
        dirNameTmp += "/";
    if (dirNameTmp[0] == '/')
        dirNameTmp = dirNameTmp.substr(1);
    if (dirPre.find_last_of("/") != dirPre.length() - 1)
        dirPre += "/";

    string path;

    path = dirPre + dirNameTmp;


    struct stat fileStat;
    DIR* pDir = opendir(path.c_str());
    if (!pDir) return;

    struct dirent* pDirEnt = NULL;
    while ( (pDirEnt = readdir(pDir)) != NULL )
    {
        if (strcmp(pDirEnt->d_name,".") == 0 || strcmp(pDirEnt->d_name,"..") == 0)
            continue;

        string tmpDir = dirPre + dirNameTmp + pDirEnt->d_name;
        if (stat(tmpDir.c_str(),&fileStat) != 0)
            continue;

        string innerDir = dirNameTmp + pDirEnt->d_name;
        if (fileStat.st_mode & S_IFDIR == S_IFDIR)
        {
            EnumDirFiles(dirPrefix,innerDir,vFiles);
            continue;
        }

        vFiles.push_back(innerDir);
    }

    if (pDir)
        closedir(pDir);
}

//压缩码流
int WriteInZipFile(zipFile zFile,const string& file)
{
    fstream f(file.c_str(),std::ios::binary | std::ios::in);
    f.seekg(0, std::ios::end);
    long size = f.tellg();
    f.seekg(0, std::ios::beg);
    if ( size <= 0 )
    {
        return zipWriteInFileInZip(zFile,NULL,0);
    }
    char* buf = new char[size];
    f.read(buf,size);
    int ret = zipWriteInFileInZip(zFile,buf,size);
    delete[] buf;
    return ret;
}

//minizip 压缩
int Minizip(string src, string dest) {
    if (src.find_last_of("/") == src.length() - 1)
        src = src.substr(0,src.length()-1);

    struct stat fileInfo;
    stat(src.c_str(), &fileInfo);
    if (S_ISREG(fileInfo.st_mode)) {
        zipFile zFile = zipOpen(dest.c_str(),APPEND_STATUS_CREATE);
        if (zFile == NULL) {
            cout<<"openfile failed"< vFiles;
        EnumDirFiles(dirPrefix, dirName, vFiles);
        vector::iterator itF = vFiles.begin();
        for (;itF != vFiles.end(); ++itF) {
            zip_fileinfo zFileInfo = { 0 };
            int ret = zipOpenNewFileInZip(zFile,itF->c_str(),&zFileInfo,NULL,0,NULL,0,NULL,0,0);
            if (ret != ZIP_OK) {
                cout<<"openfile in zip failed"<

总结:CMakelists还需要再熟悉,程序使用方式只需要输入压缩前的文件路径和之后压缩包的路径和文件名就行。

你可能感兴趣的:(C++)