QT 引入Quazip和Zlib源码工程到项目中,无需编译成库,跨平台,压缩进度

前言

最近在做项目时遇到一个需求,需要将升级的文件压缩成zip,再进行传输;

通过网络调研,有许多方式可以实现,例如QT私有模块的ZipReader、QZipWriter;或者第三方库zlib或者libzip或者quazip等;其中libzip和quazip都是依赖于zlib;

然后,这些都需要变成库,然后再链接到QT项目中进行使用;

由于项目的特殊性,有可能需要在window,Linux和ARM三个平台上去运行,如果都编译为库去使用的话,那么需要编译三个平台,甚是麻烦,而且如果系统版本不一样,可能还不能用;

所以,现阶段有两种方案,其一是使用QT自带的压缩库,其二是使用第三方库的源码;

由此可知,使用QT自带的私有库是最方便,且网络上也有教程(文章最后也提供的操作代码);

但是,使用QT自带的私有库有几个缺点,第一是需要QT5.14以上的版本才可以使用,且在QT6中已经移除了该模块;而且需要安装QT时勾选安装QT源码才可以使用;由此,这种方式pass掉;

本人在ARM平台安装QT,是使用命令行在线安装的,QT的版本无法控制,也无法安装源码!

只能使用第二种方式了,遂在网络上寻找第三方库的源码,如何将将源码潜入到QT项目中去;

网络上教程,百分之99.99都是叫你如何编译使用的,剩下百分之0.01是需要vip和付费资源,完全没有使用源码的方式;

直到我遇到了一篇博客,里面博主就是使用Quazip+Zlib源码,用于异步压缩文件为zip格式,且博主将代码开源,正好符合我的需求,再次非常感谢该博主,链接如下:

Qt+Quazip+Zlib源码工程实现带进度同步异步加解压文件_qt 压缩zip 进度-CSDN博客

但是,该项目源码也使用到了QT的私有模块,对于我这种在ARM平台下使用命令行安装的QT,且版本没有达到5.14的我来说,无疑是晴天霹雳;

项目无法运行,报错!!!

没办法,只能自己手动去修改,这难不倒身为程序员的我!

我将代码中的私有模块去掉,将博主写的压缩解压缩代码也去掉,自己动手写了一个操作类,使用了Quazip的接口,供外部使用!(同步 压缩/解压缩)

完成后,突然想起来,还有加密压缩的需求,这该怎么办呢?

在网络上调研了一整天,没啥博客能讲明白或者能使用quazip库直接给出代码的;

直到我遇到了另一篇博客,里面有分享了一些 加密压缩多个文件解压含密码的压缩文件 的案例;

通过参考这些案例,我写出来自己的加密压缩和解密压缩文件和文件夹的操作函数,经过测试可行;

再次也非常感谢该博主的分享,博文链接如下:

Qt加密压缩与解压-CSDN博客

到了这一步,项目需求的加密压缩和解密压缩基本就完成了;

但转念一想,平常事我们使用的解压缩软件时,都是带有进度条的,也就是说下解压缩时,我们应该需要知道进度;

于是乎,再次修改代码,增加了解压缩操作时,将当前进度通过信号发射出去,由调用方处理这个信号即可!

因为我实现的解压缩功能是同步的,所以,调用方在处理解压缩时,如果不希望卡屏,就得使用线程去操作;

由此写出了一个简易的解压缩zip软件,运行效果如下:

压缩成功后

解压缩和压缩文件是一样的,这里就不放出演示了!

对比一下压缩后的大小:

效果还是很明显的!


目录

前言

一、基础的解压缩

二、自定义实现解压缩

1.加密压缩

1).打开zip文件.打开zip文件)

2).获取需要压缩的文件夹内部的所有文件及子文件.获取需要压缩的文件夹内部的所有文件及子文件)

3).创建一个QuaZipFile.创建一个QuaZipFile)

4).遍历获取到的所有文件列表.遍历获取到的所有文件列表)

5).创建新的ZIP文件条目信息.创建新的ZIP文件条目信息)

6).打开ZIP文件条目.打开ZIP文件条目)

7).读取写入.读取写入)

8).关闭文件.关闭文件)

9).详细代码.详细代码)

2.解密解压缩

1).创建文件夹.创建文件夹)

2).打开zip文件.打开zip文件)

3).获取zip内的所有文件条目.获取zip内的所有文件条目)

4).遍历这个链表.遍历这个链表)

5).处理文件夹.处理文件夹)

6).创建一个QuaZipFile.创建一个QuaZipFile)

7).打开QuaZipFile.打开QuaZipFile)

8).读取写入(解压缩).读取写入(解压缩))

9).关闭文件.关闭文件)

10).详细代码.详细代码)

三、源码分享

1.下载后如何引入自己的项目工程中?

1).拷贝quazip文件夹到自己的项目工程中.拷贝quazip文件夹到自己的项目工程中)

2).在自己的项目的.pro文件引入如下代码.在自己的项目的.pro文件引入如下代码)

3).包含头文件.包含头文件)

[2.QT自带压缩库操作分享 ZipReader、QZipWriter](#2.QT自带压缩库操作分享 ZipReader、QZipWriter)

1).导入私有模块.导入私有模块)

2).zipcompress.h.zipcompress.h)

3).zipcompress.cpp.zipcompress.cpp)

四、结束语


一、基础的解压缩

网络上介绍Quazip库使用的,基本都是以下这些:

cpp 复制代码
JlCompress mJlCompress;

// 压缩文件
mJlCompress.compressFiles(fileCompressed,files);

// 解压文件夹
mJlCompress.extractDir(fileCompressed, dir);

// 压缩文件夹
mJlCompress.compressDir(fileCompressed, dir, recursive);

// 解压文件
mJlCompress.extractFiles(fileCompressed, files);

其实如果是基础用法,上面这几句代码也够用了;

但是如果涉及到加密压缩和进度方面,就得自己去实现解压缩的过程了,且这样也更加灵活一点!

二、自定义实现解压缩

Quazip库还提供了QuaZipQuaZipFileQuaZipNewInfoQuaZipFileInfo

等类供我们自己去处理!

QuaZip 类用于打开一个.zip文件;

QuaZipFile 类用于处理zip内部的文件,即读取zip内部文件数据(解压)或者往zip内部写入文件(压缩);【在此可以进行加密和解密处理】

QuaZipNewInfo 类用于定义一个zip的文件信息,在压缩时使用;

QuaZipFileInfo类用于处理一个zip内部的文件;

当然,还有以下这么多:(别家复制过来的)

说明
JlCompress 典型操作工具类
QuaAdler32 Adler32算法校验和
QuaChecksum32 校验和接口
QuaCrc32 CRC32校验和
QuaGzipFile GZIP 文件操作
QuaZIODevice 压缩/解压 QIODevice
QuaZip ZIP 文件
QuaZipDir ZIP文件内目录导航
QuaZipFile ZIP文件内的文件
QuaZipFileInfo ZIP压缩包内的文件信息
QuaZipFilePrivate QuaZip的接口
QuaZipNewInfo 被创建的文件信息
QuaZipPrivate QuaZIP内部类

下面是加密压缩和解密压缩的过程分析;

1.加密压缩

这里处理的是压缩文件夹,压缩文件与之类似;

压缩后的文件结构与原来一致;

1).打开zip文件

cpp 复制代码
QuaZip newZip(fileCompressed); // 要生成的zip文件                         
if (!newZip.open(QuaZip::mdCreate)) {                               
    qDebug() << "Failed to create ZIP file:" << fileCompressed;                                 
    return false;                                                  
}

参数枚举介绍:

cpp 复制代码
enum Mode {
    mdNotOpen,        ///< ZIP文件未打开。这是初始模式。
    mdUnzip,          ///< ZIP文件已打开,用于读取其内部的文件。
    mdCreate,         ///< ZIP文件已通过open()调用创建。
    mdAppend,         ///< ZIP文件以追加模式打开。这指的是ZIP/UNZIP包中的APPEND_STATUS_CREATEAFTER模式,
                      ///  意味着zip被追加到某个已存在的文件中,该文件包含自解压代码。这显然不是您想要用来
                      ///  向现有的ZIP归档添加文件的模式。
    mdAdd             ///< ZIP文件已打开,用于向归档中添加文件。
};

一般来说,我们只需要用到 mdUnzip 用于解压缩 和 mdCreate 用于压缩即可!

2).获取需要压缩的文件夹内部的所有文件及子文件

cpp 复制代码
QStringList filePathList = 获取所有文件();

3).创建一个QuaZipFile

cpp 复制代码
QuaZipFile zipFile(&newZip);

使用QuaZip作为参数;

4).遍历获取到的所有文件列表

在循环体内部处理压缩事项;以下操作都是在循环体内部进行;

5).创建新的ZIP文件条目信息

cpp 复制代码
QuaZipNewInfo info(文件名, 文件路径+文件名);

6).打开ZIP文件条目

cpp 复制代码
if (!zipFile.open(QIODevice::WriteOnly, info, password.toUtf8().constData(), 0, 8)) {  
    qDebug() << "Failed to open ZIP entry for writing:" << fileName;                            
    // 关闭ZIP                                                                                    
    newZip.close();                                                                                                                                
    return false;                                                                              
}

open参数介绍:

cpp 复制代码
bool open(
    OpenMode mode,               // 打开模式,指定是以什么方式打开文件(例如,只写、追加等)
    const QuaZipNewInfo& info,   // 文件信息,包括文件名、时间戳等
    const char *password = nullptr, // 密码,用于加密文件,如果不需要加密则传递nullptr
    quint32 crc = 0,             // CRC校验码,通常设置为0,除非在原始模式下使用
    int method = Z_DEFLATED,     // 压缩方法,Z_DEFLATED表示使用Deflate算法,Z_BZIP2ED表示使用BZIP2算法,0表示不压缩
    int level = Z_DEFAULT_COMPRESSION, // 压缩级别,对于Deflate算法,可以是0-9之间的值,Z_DEFAULT_COMPRESSION表示默认级别
    
    // 以下保持默认即可!!!
    bool raw = false,            
    int windowBits = -MAX_WBITS, 
    int memLevel = DEF_MEM_LEVEL,
    int strategy = Z_DEFAULT_STRATEGY 
);

需要注意的是,

src参数,通常设置为0,除非你知道使用其他值,所带来的后果;

method参数,需要设置为8,即宏Z_DEFLATED,这个是压缩算法,注意,quazip只支持这种算法,所以必须设置为8;

level参数,是压缩等级,可设置0-9,之间的任何一个数字,0表示无压缩,最快,9表示最大压缩,但最慢,一般设置为默认值即可!

其实也就是说,只需要设置前面三个参数即可!!!

7).读取写入

使用QFile读取本地文件数据,写入QuaZipFile中

cpp 复制代码
QFile sourceFile(filePath);
sourceFile.open(QIODevice::ReadOnly);
zipFile.write(sourceFile.readAll());    // 注意,处理大文件时,这里会崩溃

注意,上面写法在处理大文件时会有问题,readAll()函数会将文件数据读如内存中,如果文件太大,会将堆内存给撑爆,程序就闪退了;

所以为了避免这样的问题,在处理大文件时,必须分块进行处理!

cpp 复制代码
QByteArray buffer;                                    
while(!sourceFile.atEnd()) {                          
    buffer = sourceFile.read(4096);    // 每次读取一页内存数据          
    zipFile.write(buffer);                            
}

8).关闭文件

最后记得在循环尾部将文件关闭后,再进行新一轮的文件读写操作!

cpp 复制代码
sourceFile.close();
zipFile.close();

处理完毕后,记得关闭 newZip.close();

加密压缩文件部分与之类似,这里就不展开讲解了!

给出函数接口,自己动手去实现一下吧;

cpp 复制代码
    /**
     * @brief 加密压缩多个文件
     * @param fileCompressed        压缩包名
     * @param files                 要解压的文件列表
     * @param password              密码
     * @return
     */
    bool compressFilesWithPassword(const QString &fileCompressed,const QStringList &files,const QString& password);

9).详细代码

进度部分就不详细讲解了,都在代码函数中

cpp 复制代码
/**                               
 * @brief 加密压缩文件夹内的所有文件           
 * @param fileCompressed    压缩包名-路径  
 * @param dir               压缩路径  
 * @param password          密码    
 * @return                        
 */                               
bool zipCompress::compressDirsWithPassword(const QString &fileCompressed, const QString &dir, const QString &password) {
    bool result = false;

    if (fileCompressed.isEmpty() || dir.isEmpty()) {
        emit signalCompressDirinish(result);
        return result;
    }

    QuaZip newZip(fileCompressed); // 要生成的zip文件
    if (!newZip.open(QuaZip::mdCreate)) {
        qDebug() << "Failed to create ZIP file:" << fileCompressed;
        emit signalCompressDirinish(result);
        return result;
    }

    // 读取目录中的所有文件
    QStringList filePathList = listFilesInDirectoryRecursively(dir);
    if (filePathList.isEmpty()) {
        qDebug() << "No files to compress in directory:" << dir;
        newZip.close();
        emit signalCompressDirinish(result);
        return result;
    }

    qreal pro = 100.0 / filePathList.size();
    qreal progress = 1.0;

    QuaZipFile zipFile(&newZip);
    for (const QString &filePath : filePathList) {
        // 构造相对于dir的文件名
        QString fileName = QDir(dir).relativeFilePath(filePath);

        // 创建ZIP文件条目信息
        QuaZipNewInfo info(fileName, filePath);

        // 尝试打开ZIP文件条目进行写入
        if (!zipFile.open(QIODevice::WriteOnly, info, password.toUtf8().constData(), 0, 8)) {
            qDebug() << "Failed to open ZIP entry for writing:" << fileName;
            // 关闭ZIP
            newZip.close();
            emit signalCompressDirinish(result);
            return result;
        }

        // 打开源文件进行读取
        QFile sourceFile(filePath);
        if (!sourceFile.open(QIODevice::ReadOnly)) {
            qDebug() << "Failed to open source file for reading:" << filePath;
            // 关闭ZIP
            newZip.close();
            emit signalCompressDirinish(result);
            return result;
        }

        // 总进度
        emit signalCompressionProgress(progress, "1", filePath);

        // 大文件读取分块处理,否则程序会闪退
        {
            qreal file_pro = 100.0 / (sourceFile.size() / mBlockSize);
            qreal file_progress = 0.0;

            // 将源文件的内容写入ZIP文件
            QByteArray buffer;
            while(!sourceFile.atEnd()) {
                buffer = sourceFile.read(mBlockSize);
                zipFile.write(buffer);

                file_progress += file_pro;
                emit signalFileProgress(file_progress, filePath);
            }

            emit signalFileProgress(100, filePath);
        }

        sourceFile.close();
        zipFile.close();

        progress += pro;
        progress = qBound(0.0, progress, 99.999);
    }


    result = true;
    newZip.close();

    emit signalCompressionProgress(100, "1", "");
    emit signalCompressDirinish(result);

    return result;
}




QStringList zipCompress::listFilesInDirectoryRecursively(const QString &directoryPath) {
    QStringList list;

    QDirIterator it(directoryPath, QDir::Files, QDirIterator::Subdirectories);
    while (it.hasNext()) {
        QString filePath = it.next();
        list.append(filePath);
    }

    return list;
}

2.解密解压缩

这里处理的是解压缩一个zip文件;

解压出来文件结构与压缩包内一致!

1).创建文件夹

判断传进来的路径解压路径,如果不存在则创建

2).打开zip文件

cpp 复制代码
QuaZip zip(fileCompressed);                                       
if (!zip.open(QuaZip::mdUnzip)) {                                 
    qDebug() << "Failed to open ZIP file:" << fileCompressed;                          
    return false;                                                
}

因为是解压缩,所以参数使用mdUnzip

3).获取zip内的所有文件条目

cpp 复制代码
QList<QuaZipFileInfo> fileInfoList = zip.getFileInfoList();

4).遍历这个链表

解压缩操作都在这个循环体内进行;

5).处理文件夹

如果处理的当前文件,在本机电脑中还没有路径,则进行创建;

且跳过是文件夹的操作!

6).创建一个QuaZipFile

cpp 复制代码
QuaZipFile zipFile(zip.getZipName(), 文件名);

7).打开QuaZipFile

cpp 复制代码
zipFile.open(QIODevice::ReadOnly, password.toUtf8().constData());

参数二是密码;

8).读取写入(解压缩)

注意,为了防止大文件的问题,读取写入是还是分块进行操作!

cpp 复制代码
QByteArray buffer;                                        
while(!zipFile.atEnd()) {                                 
    buffer = zipFile.read(4096);                    
    outFile.write(buffer);                                  
}

9).关闭文件

最后记得在循环尾部将文件关闭后,再进行新一轮的文件读写操作!

cpp 复制代码
outFile.close();    
zipFile.close();    
复制代码
处理完毕后,记得关闭 zip.close();

10).详细代码

进度部分就不详细讲解了,都在代码函数中

cpp 复制代码
bool zipCompress::extractDirWithPassword(const QString &fileCompressed, const QString &dir, const QString &password) {
    bool result = false;

    if (fileCompressed.isEmpty() || dir.isEmpty()) {
        emit signalExtractDirFinish(result);
        return result;
    }

    // 使用QFileInfo获取文件名(不带扩展名)并构建目标目录路径
    QFileInfo fileInfo(fileCompressed);
    QString targetDirName = fileInfo.completeBaseName();
    QString targetDirPath = QDir(dir).absoluteFilePath(targetDirName);

    // 创建目标目录(如果不存在)
    QDir targetDir(targetDirPath);
    if (!targetDir.exists() && !targetDir.mkpath(".")) {
        qDebug() << "Failed to create target directory:" << targetDirPath;
        emit signalExtractDirFinish(result);
        return result;
    }

    // 打开ZIP文件
    QuaZip zip(fileCompressed);
    if (!zip.open(QuaZip::mdUnzip)) {
        qDebug() << "Failed to open ZIP file:" << fileCompressed;
        emit signalExtractDirFinish(result);
        return result;
    }

    // 遍历ZIP文件中的所有条目
    QList<QuaZipFileInfo> fileInfoList = zip.getFileInfoList();

    qreal pro = 100.0 / fileInfoList.size();
    qreal progress = 1.0;

    for (const QuaZipFileInfo &fileInfoEntry : fileInfoList) {
        // 组合目标文件路径
        QString fileName = fileInfoEntry.name;
        QString filePath = targetDir.absoluteFilePath(fileName);

        // 如果是文件夹,如果不存在则创建;然后跳过文件夹的操作
        QFileInfo info(filePath);
        if (info.isDir()) {
            QDir().mkpath(filePath);
            continue;

        } else {    // 如果是文件,如果路径不存在,创建该路径
            QString path = info.path();
            QDir dpath(path);
            if (!dpath.exists()) {
                if (!dpath.mkpath(path)) {
                    qDebug() << "Failed to create directory:" << path;
                    emit signalExtractDirFinish(result);
                    return result;
                }
            }
        }


        // 打开ZIP条目并解压文件
        QuaZipFile zipFile(zip.getZipName(), fileName);
        if (zipFile.open(QIODevice::ReadOnly, password.toUtf8().constData())) {
            QFile outFile(filePath);
            if (!outFile.open(QIODevice::WriteOnly)) {
                qDebug() << "Failed to open output file for writing:" << filePath;
                zipFile.close();
                zip.close();
                emit signalExtractDirFinish(result);
                return result;
            }

            emit signalCompressionProgress(progress, "2", filePath);

            // 大文件读取分块处理,否则程序会闪退
            {
                qreal file_pro = 100.0 / (zipFile.size() / mBlockSize);
                qreal file_progress = 0.0;

                // 解压并写入文件
                QByteArray buffer;
                while(!zipFile.atEnd()) {
                    buffer = zipFile.read(mBlockSize);
                    outFile.write(buffer);

                    file_progress += file_pro;
                    emit signalFileProgress(file_progress, filePath);
                }

                emit signalFileProgress(100, filePath);
            }

            outFile.close();
            zipFile.close();
        } else {
            qDebug() << "Failed to open ZIP entry for reading:" << fileName;
            zip.close();
            emit signalExtractDirFinish(result);
            return result;
        }

        progress += pro;
        progress = qBound(0.0, progress, 99.999);
    }


    result = true;
    // 关闭ZIP文件
    zip.close();

    emit signalCompressionProgress(100, "2", "");
    emit signalExtractDirFinish(result);

    return result;
}

三、源码分享

到此,解压缩已经介绍完毕,现在分享我参考写的解压缩程序

https://download.csdn.net/download/cpp_learner/90411497https://download.csdn.net/download/cpp_learner/90411497因为我这边编写的压缩和解压缩操作都是同步的,所以,建议操作时使用线程去处理,否则会卡屏,而且进度条也无法使用;

在我给出的案例工程中,就是使用了线程去解压缩等操作,有兴趣可以学习一下!

1.下载后如何引入自己的项目工程中?

1).拷贝quazip文件夹到自己的项目工程中

2).在自己的项目的.pro文件引入如下代码

cpp 复制代码
# 源码方式使用需要设置为静态库
DEFINES +=   QUAZIP_STATIC
include($$PWD/quazip/3rdparty/zlib.pri)
include($$PWD/quazip/quazip.pri)
include($$PWD/quazip/zipop/zipop.pri)

3).包含头文件

cpp 复制代码
#include "zipcompress.h"

头文件包含后,就可以直接使用了

cpp 复制代码
compressionTool::zipCompress m_zipCompress;                                  
// 压缩文件夹                                                                     
m_zipCompress.compressDirsWithPassword(mZipPath, mPath, mPassword);        
                                                                             
// 解压缩                                                                       
m_zipCompress.extractDirWithPassword(fileName, fileinfo.path(), "abc@123");  
                                                                             
// 压缩文件                                                                    
m_zipCompress.compressFilesWithPassword(mZipPath, mFiles, mPassword);      

2.QT自带压缩库操作分享 ZipReader、QZipWriter

以下是我编写好的操作类,直接新建文件拷贝代码到文件中即可使用!

(注意,一般来说,需要QT5.14以上的版本才可以使用)

1).导入私有模块

在.pro文件中添加私有模块

cpp 复制代码
QT       += gui-private

2).zipcompress.h

cpp 复制代码
#ifndef ZIPCOMPRESS_H
#define ZIPCOMPRESS_H

#include <QObject>
#include <QtGui/private/qzipreader_p.h>
#include <QtGui/private/qzipwriter_p.h>


class ZipCompress : public QObject
{
    Q_OBJECT
public:
    ZipCompress(QObject *parent = nullptr);


    /**
     * @brief 压缩文件
     * @param fileNames 需要压缩的文件名
     * @param saveName  压缩后的文件路径和名字
     */
    bool zipCompressFile(const QStringList &fileNames, const QString &saveName);



    /**
     * @brief 压缩文件夹
     * @param dirName   需要压缩的文件夹名
     * @param saveName  压缩后的文件路径和名字
     */
    bool zipCompressDirector(const QString &dirName, const QString &saveName);



    /**
     * @brief 解压缩
     * @param zipFile   压缩包
     * @param saveDir   解压路径
     * @return
     */
    bool zipUnCompressFile(const QString &zipFile, const QString &saveDir);



private:
    /**
     * @brief 递归压缩
     * @param zipWriterHandle       QZipWriter指针
     * @param zipParentDirName      父路径,相对路径
     * @param srcDir                当前需要处理的文件夹路径,绝对路径
     */
    void zipCompressDirector(void *zipWriterHandle, const QString &zipParentDirName, const QString &srcDir);


private:
    QZipReader *mZipReader;
    QZipWriter *mZipWriter;
};

#endif // ZIPCOMPRESS_H

3).zipcompress.cpp

cpp 复制代码
#include "zipcompress.h"

#include <QFileInfo>
#include <QDir>
#include <QDebug>

ZipCompress::ZipCompress(QObject *parent)
    : QObject(parent)
{
}

bool ZipCompress::zipCompressFile(const QStringList &fileNames, const QString &saveName)
{
    QZipWriter *zipWriter = new QZipWriter(saveName);
    if (!zipWriter) {
        qDebug() << "压缩失败!";
        return false;
    }

    QFile file;
    QFileInfo fileInfo;
    foreach (const QString &fileName, fileNames) {
        if (fileName.isEmpty() || "" == fileName) {
            continue;
        }

        // 判断文件是否存在
        fileInfo.setFile(fileName);
        if (!fileInfo.exists()) {
            qDebug() << fileName << " : 文件不存在!";
            continue;
        }

        if (fileInfo.isFile()) {
            // 打开文件
            file.setFileName(fileName);
            if (!file.open(QIODevice::ReadOnly)) {
                qDebug() << fileName << " : 文件打开失败!";
                continue;
            }

            // 添加到压缩包中
            zipWriter->addFile(fileInfo.fileName(), file.readAll());
            file.close();

        } else if (fileInfo.isDir()) {
            // 添加到压缩包中
            zipWriter->addDirectory(fileName);
        }
    }

    zipWriter->close();
    if (zipWriter) {
        delete zipWriter;
        zipWriter = nullptr;
    }

    return true;
}

bool ZipCompress::zipCompressDirector(const QString &dirName, const QString &saveName)
{
    QFile file(saveName);
    if (!file.open(QFile::WriteOnly)) {
        qDebug() << "压缩失败!";
        return false;
    }

    std::shared_ptr<QZipWriter> zipWriter(new QZipWriter(&file));
    if (!zipWriter) {
        qDebug() << "压缩失败!";
        return false;
    }


    zipCompressDirector(zipWriter.get(), "", dirName);
    zipWriter->close();
    file.close();

    return true;
}

bool ZipCompress::zipUnCompressFile(const QString &zipFile, const QString &saveDir)
{
    QFile file(zipFile);
    if (!file.open(QIODevice::ReadOnly)) {
        qDebug() << zipFile << " : 文件打开失败!";
        return false;
    }

    QDir dir(saveDir);
    if (!dir.exists()) {
        if (!dir.mkpath(saveDir)) { // 创建文件夹
            qDebug() << saveDir << " : 文件夹路径不存在,且创建失败!";
            return false;
        }
    }

    std::shared_ptr<QZipReader> zipReader(new QZipReader(&file));
    return zipReader->extractAll(saveDir);  // 全部解压出来
}

void ZipCompress::zipCompressDirector(void *zipWriterHandle, const QString &zipParentDirName, const QString &srcDir)
{
    QZipWriter *zipWriter = (QZipWriter *)zipWriterHandle;
    QDir directory(srcDir);
    QFileInfoList fileList = directory.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);

    for (const QFileInfo &fileInfo : fileList) {
        QString relatePath = fileInfo.fileName();       // 获取当前文件名 | 文件夹名

        if (!zipParentDirName.isEmpty()) {
            relatePath.prepend(zipParentDirName + "/"); // 头部拼接上父路径,相对路径
        }

        QString filePath = fileInfo.absoluteFilePath(); // 获取当前文件的绝对路径
        if (fileInfo.isDir()) {
            // 添加文件夹
            zipWriter->addDirectory(relatePath);
            // 参数二:文件夹相对路径      参数三:文件夹绝对路径
            zipCompressDirector(zipWriter, relatePath, filePath);

        } else {
            QFile file(filePath);
            if (!file.open(QIODevice::ReadOnly)) {
                qDebug() << filePath << " : 文件打开失败!";
                continue;
            }

            zipWriter->addFile(relatePath, file.readAll());
            file.close();
        }
    }
}

四、结束语

文章最后,感谢各位能够坚持看完,相信此篇文章也会对你有所帮助;

当然,我上面所给出的只是一些基础用法,还有很多高级用法我也还没整明白;

或者哪位大佬有更好的实现方式,也欢迎评论区分享出来,供大家一起探讨学习;

完!

相关推荐
数巨小码人7 小时前
QT SQL框架及QSqlDatabase类
jvm·sql·qt
程序员老舅9 小时前
C++ Qt项目教程:WebServer网络测试工具
c++·qt·测试工具·webserver·qt项目·qt项目实战
enyp8011 小时前
Qt QStackedWidget 总结
开发语言·qt
luoyayun36111 小时前
Trae+Qt+MSVC环境配置
vscode·qt·环境配置·trae qt
水瓶丫头站住19 小时前
Qt中QDockWidget的使用方式
开发语言·qt
laimaxgg19 小时前
Qt常用控件之数字显示控件QLCDNumber
开发语言·c++·qt·qt5·qt6.3
牵牛老人20 小时前
Qt开发中出现中文乱码问题深度解析与解决方案
开发语言·qt
Zfox_20 小时前
【QT】信号与槽 & 窗口坐标
开发语言·c++·qt·qt5
进击ing小白1 天前
Qt程序退出相关资源释放问题
开发语言·qt