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

Qt三方库:QuaZIP实战指南——从编译到多场景应用 本文详细介绍了Qt三方库QuaZIP的编译与多场景应用实战指南。从环境准备、编译技巧到项目集成,再到日志打包、资源加密等高频使用场景,全面解析如何高效利用QuaZIP处理压缩解压需求。特别针对中文路径、大文件处理等常见问题提供了解决方案,帮助Qt开发者提升开发效率。 阅读详情
AI摘要

本文介绍了如何在QT项目中引入Quazip和Zlib源码工程,实现跨平台的加密压缩功能,并提供进度反馈。详细步骤包括基础解压缩、自定义加密解压缩、源码引入方法以及使用QT自带压缩库的分享。文章还强调了Quazip库的使用限制和安全注意事项。

前言

最近在做项目时遇到一个需求,需要将升级的文件压缩成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 进度-优快云博客

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

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

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

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

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

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

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

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

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

Qt加密压缩与解压-优快云博客

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

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

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

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

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

压缩成功后

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

对比一下压缩后的大小:

效果还是很明显的!


目录

前言

一、基础的解压缩

二、自定义实现解压缩

1.加密压缩

1).打开zip文件

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

3).创建一个QuaZipFile 

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

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

6).打开ZIP文件条目

7).读取写入

8).关闭文件

9).详细代码

2.解密解压缩

1).创建文件夹

 2).打开zip文件

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

4).遍历这个链表

5).处理文件夹

 6).创建一个QuaZipFile 

7).打开QuaZipFile

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

 9).关闭文件

10).详细代码

三、源码分享

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

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

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

3).包含头文件

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

1).导入私有模块

2).zipcompress.h

3).zipcompress.cpp

四、结束语


一、基础的解压缩

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

JlCompress mJlCompress;

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

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

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

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

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

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

二、自定义实现解压缩

Quazip库还提供了QuaZip、QuaZipFile、QuaZipNewInfo、QuaZipFileInfo

等类供我们自己去处理!

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

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

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

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

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

类说明
JlCompress典型操作工具类
QuaAdler32Adler32算法校验和
QuaChecksum32校验和接口
QuaCrc32CRC32校验和
QuaGzipFileGZIP 文件操作
QuaZIODevice压缩/解压 QIODevice
QuaZipZIP 文件
QuaZipDirZIP文件内目录导航
QuaZipFileZIP文件内的文件
QuaZipFileInfoZIP压缩包内的文件信息
QuaZipFilePrivateQuaZip的接口
QuaZipNewInfo被创建的文件信息
QuaZipPrivateQuaZIP内部类

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

1.加密压缩

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

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

1).打开zip文件

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

参数枚举介绍:

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

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

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

QStringList filePathList = 获取所有文件();

3).创建一个QuaZipFile 

QuaZipFile zipFile(&newZip);

使用QuaZip作为参数;

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

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

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

QuaZipNewInfo info(文件名, 文件路径+文件名);

6).打开ZIP文件条目

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参数介绍:

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中

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

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

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

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

8).关闭文件

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

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

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

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

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

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

9).详细代码

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

/**                               
 * @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文件

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

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

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

QList<QuaZipFileInfo> fileInfoList = zip.getFileInfoList();

4).遍历这个链表

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

5).处理文件夹

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

且跳过是文件夹的操作!

 6).创建一个QuaZipFile 

QuaZipFile zipFile(zip.getZipName(), 文件名);

7).打开QuaZipFile

zipFile.open(QIODevice::ReadOnly, password.toUtf8().constData());

参数二是密码;

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

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

QByteArray buffer;                                        
while(!zipFile.atEnd()) {                                 
    buffer = zipFile.read(4096);                    
    outFile.write(buffer);                                  
}

 9).关闭文件

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

outFile.close();    
zipFile.close();    
处理完毕后,记得关闭 zip.close();

10).详细代码

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

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

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

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

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

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

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

3).包含头文件

#include "zipcompress.h"

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

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文件中添加私有模块

QT       += gui-private

2).zipcompress.h

#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

#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();
        }
    }
}

四、血的教训 - 2025年5月28日

注意,QuaZip仅支持 ZipCrypto 加密方式,这种加密方式安全性低,只适用于临时加密场景。

如果说,外部的zip压缩包(手动压缩或者java程序等生成的压缩包)使用的是AES加密方式,那么QuaZip库是无法解密解压缩的,除非改用ZipCrypto 加密方式。

请记住这一点,我在这踩过坑!!!

五、结束语

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

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

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

完!

告别手动打包!用QuaZIP在Qt项目中轻松实现文件压缩与解压(附完整配置流程) 本文详细介绍了如何在Qt项目中使用QuaZIP库实现文件压缩与解压功能,包括跨平台编译配置、项目集成方法及实战代码示例。QuaZIP作为Qt生态中的高效压缩库,能显著减少代码量并提升开发效率,特别适合日志归档、资源打包等场景。文章还提供了性能优化、加密压缩等进阶技巧,帮助开发者快速掌握这一实用工具。 阅读详情

相关推荐

QT案例 Qt Creator 使用QuaZIP加密压缩解压ZIP文件

QT开发中部分项目可能会涉及对项目数据的一些指定文件的打包压缩以及指定目录下的解压,此时也需要对数据数据进行加密以确保数据的安全性。此时就可以使用Quazip实现相关功能。 QuaZIP是使用Qt,C++对ZLIB进行简单封装的用于压缩ZIP以及解压缩ZIP的开源库。

... 4155

使用QuaZip对文件进行压缩解压操作

八月份快要过去了,突然想到我还没有写一篇日志呢,想一想这一个月我并没有做开发以外的事情,三十天来还是尝试并且解决了不少技术上的问题的。所以这次我打算将其中一些作为日志分享出来。

开发游戏,辉煌全中国 5214

使用Qt编译和应用QuaZip

接下来,我们将创建一个新的Qt项目,并将QuaZip源代码包含到项目中。在项目向导中,选择"Qt Widgets Application"模板,并按照向导的指导完成项目的创建过程。然后,我们编写了一个简单的应用程序,展示了如何创建ZIP文件并向其中添加文件。然后,右键单击项目文件夹,选择"Add Existing Files",并选择QuaZip源代码文件以将其添加到项目中。在这个示例中,我们创建了一个名为"archive.zip"的ZIP文件,并向其中添加了一个名为"file.txt"的文件。

HackLogic的博客 409

Qt使用Quazip直接读取压缩包内文件

做项目的时候需要对压缩包内的文件进行读取和修改,在网上找了很久也没有发现相关的资料,索性自己研究了一下,现在分享大家。

小老鼠的博客 5731

使用QuaZipFile进行加密后形成的压缩包,用WinRAR,Bandizip等可以解压出来文件,用360解压,7-zip等解压后的为空

【代码】使用QuaZipFile进行加密后形成的压缩包,用WinRAR,Bandizip等可以解压出来问价,用360解压,7-zip等解压后的为空。

十三阿哥的博客 543

Qt压缩解压实战:QuaZip与zlib完整指南

在Qt桌面开发中,文件压缩与解压是常见的工程需求。理解底层压缩库与上层封装库的关系,是技术选型的关键。zlib是提供deflate算法的底层压缩库,负责数据流压缩;zip则是在该数据流之上封装文件名、目录结构等容器信息。QuaZip作为Qt风格的封装,基于QIODevice实现,让开发者以熟悉的接口操作zip格式,极大降低了集成成本。从单文件打包到递归目录压缩,从中文编码处理到路径安全防护,QuaZip在客户端工具、日志打包、数据导出等真实场景中展现出了稳定性和实用性。配合CMake构建与依赖部署规范,可实

weixin_28931507的博客 316

quazip压缩的用法

quazip

weixin_32895669的博客 1159

Qt使用QuaZIP压缩以及解压缩文件

内有libzip、quazip源码、编译生成的库文件,以及使用QuaZIP的一个测试程序代码。 环境是Windows,VS2022,Qt5.15.2,代码仅供参考

Qt之QuaZIP(zip压缩/解压缩)

简述 QuaZIP是使用Qt/C++对ZLIB进行简单封装的用于压缩及解压缩ZIP的开源库。适用于多种平台,利用它可以很方便的将单个或多个文件打包为zip文件,且打包后的zip文件可以通过其它工具打开。 Qt中提供了qCompress/qUncompress来进行文件的压缩与解压,但存在两个问题: 无法很好地压缩/解压缩文件夹。...

weixin_34259159的博客 1597

Vmware安装windowsServer2022版本

全网最详细的Vmware安装windowsServer2022版本

A乐神的博客 7004

在Redroid容器中构建Frida RPC服务:自动化生成淘宝X-Sign签名参数

本文详细介绍了在Redroid容器中构建Frida RPC服务,实现自动化生成淘宝X-Sign等签名参数的完整方案。通过逆向分析定位关键方法,定制Redroid系统使Frida-Server常驻运行,并编写Frida脚本将签名方法暴露为RPC接口,最终封装为可远程调用的微服务,解决了签名生成的可移植性与工程化难题。

ice55的博客 643

Qt项目实战:用Quazip源码集成搞定带进度条的文件压缩解压(附完整工程)

本文详细介绍了如何在Qt项目中通过源码集成Quazip和Zlib实现带进度监控的文件压缩解压功能。从工程准备、核心架构设计到UI集成和进阶优化,提供了完整的解决方案和最佳实践,特别适合需要处理大文件或要求精细进度反馈的桌面应用开发。

weixin_29232121的博客 348

【Docker】从零构建达梦DM8轻量级服务镜像:实战与优化

本文详细介绍了从零开始构建达梦DM8轻量级Docker镜像的完整实战流程。通过分析传统安装方式的痛点,阐述了使用Docker封装数据库的优势,并重点讲解了如何利用静默安装、精简组件、多阶段构建等优化技巧,打造一个体积小巧、启动迅速、配置灵活的DM8服务镜像,助力实现开发、测试与部署的环境一致性与高效性。

ooo22的博客 518

QT Word模板 + QuaZIP + LibreOffice,跨平台方案实现导出.docx文件后再转为.pdf文件

本文介绍了使用QT实现跨平台导出.docx文件并将其转换为.pdf文件的方法。由于QT缺乏原生支持,文中采用模板替换方案,结合QuaZIP和LibreOffice实现功能。主要流程包括:1)准备带占位符的.docx模板;2)使用QuaZIP解压模板文件;3)修改XML内容替换文本和图片;4)重新压缩为.docx文件;5)通过LibreOffice命令行工具转换为PDF。文章详细说明了QuaZIP库的源码集成方式、LibreOffice的跨平台安装方法,以及模板制作规范(包括占位符设置和图片处理要求)。

cpp_learner的博客 1435

Golang内存管理:GC调优实战案例

在Golang编程中,内存管理是一个非常重要的方面。良好的内存管理可以提高程序的性能和稳定性,而GC(垃圾回收)调优则是优化内存管理的关键手段。本文的目的就是通过实际案例,深入讲解Golang中GC调优的方法和技巧,让读者能够在实际项目中更好地进行内存管理和性能优化。范围涵盖了从核心概念的解释到具体代码实现和调优过程的详细分析。本文首先会介绍一些相关的术语和核心概念,让读者对Golang内存管理和GC有一个基本的认识。然后通过故事引入的方式,更加形象地解释核心概念及其相互关系。

AI Agent Harness Engineering 1118

FFMPEG音频开发: Linux下采集摄像头(使用V4L2框架)数据录制成MP4视频保存到本地

一、环境介绍 操作系统介绍:ubuntu 18.04 FFMPEG版本: 4.4.2 摄像头: USB摄像头、虚拟机挂载本机自带摄像头 二、FFMPEG与X264下载编译 X264下载地址: http://www.videolan.org/developers/x264.html FFMPEG下载地址:https://ffmpeg.org/download.html Yasm ...

8868

关于QuaZIP库的压缩使用(多级目录压缩)

最近了解了下Qt的压缩库,发现很多人推荐QuaZIP,自己捣鼓了下,写下笔记。 我这边需要的压缩结构大概如下: 即多级目录和子文件压缩。 首先是创建一个ZIP文件,用到QuaZIP。 (以下代码只是大概,没有判断执行是否成功等一些条件,自己写时记得加判断) QuaZip zip("D:\\qua.zip"); zip.open(QuaZip::mdCreate);//创建一个zip XXXXXX; zip.close(); 接着因为要操作ZIP里的文件,所以需要QuaZipFile类。且需要在ZIP里面

屁股大象的博客 1342

【Unity 实用工具篇】 | Book Page Curl 快速实现翻书效果

游戏和应用开发中,真实感的交互设计能显著提升用户体验。Unity3D图书翻页效果插件为开发者提供了一种便捷方式,可在项目中实现高度拟真的书籍翻页动画。 本文介绍该插件的快速使用方法,涵盖从基础导入到自动翻页效果创建的全过程,让我们快速实现翻页效果。

努力前行,总会成为自己心中的那道光 1万+

【Qt开发笔记】Qt实现zip压缩和解压,编译、调用zlib和QuaZip动态库过程详解

之前有个小项目中需要对zip压缩文件进行压缩和解压操作,需要用到zlib库,使用Qt开发的话可以用到已经封装好的QuaZip。作为一枚新人程序员应有的习惯,我将整个过程整理成了这篇文章,有不妥的地方还希望看到的朋友能够指出,谢谢!开发环境操作系统:Windows 7 x64 Qt版本:Qt 4.8.4 编译器:MSVC2010 zlib版本:zlib-1.2.11 QuaZip版本:QuaZ

专注Qt与C++开发 7583

用 SemanticObject 把字段变成可点击链接:Fiori Elements Navigation Using a Link 的工程化实践

SAP Fiori elements 通过 Common.SemanticObject 注解可将字段转为可点击链接,实现应用间跳转。当源字段名与目标属性名不一致时,需使用 Common.SemanticObjectMapping 进行映射。该功能依赖 Fiori Launchpad 的目标映射配置,确保正确解析 semantic object + action 并传递参数。常见误区包括未配置目标映射或字段映射错误,需逐一检查语义标注、intent 解析和参数传递链路。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 271

微信小程序 - 最新将页面可分享到朋友圈功能,小程序实现分享到朋友圈功能,开启分享给好友及分享朋友圈功能(微信小程序怎么分享到朋友圈?详细流程及示例代码教程)

没有设置过分享朋友圈功能的小程序,分享朋友圈按钮是灰色且无法点击。小程序 vue2 | vue3 版本语法都能使用,跟着教程复制代码运行即可。如下图所示,将页面开启分享后便可由用户转发出去。

🏆 前端领域优质创作者 2416

基于CMake的Quazip编译及调用(MinGW编译器)

基于CMake的QuaZip压缩库的编译与使用(基于MinGW编译器)

kf_lirui的博客 1091

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Qt+Quazip+Zlib源码工程实现带进度同步异步加解压文件

3.使用 Quazip需要自己实现进度数据回显,实现难度低故采用(源码方式引入Quazip+Zlib无需单独编译Quazip+Zlib库)。1.使用Qt自带的Qzip 由于Qzip存在Bug无法解压2G以上文件需要去修改Qt源代码故放弃。2.使用qt的lib7z库实现加解压文件时文件和文件路径不能带有中文,故放弃。2.使用Qt打包工具中带的Qtlib7z。1.使用Qt自带的Qzip。实现带进度显示的文件加解压。3.使用 Quazip。

weixin_44111250的博客 1251

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Quazip的使用

Quazip下载地址: https://sourceforge.net/projects/quazip 我下的是 quazip-0.7.2.zip解压后,打开最外层的工程文件: quazip.pro 将SUBDIRS中的qztest删掉,即: SUBDIRS=quazip在quazip/quazip.pro 中 win32{}中加入以下两句:INCLUDEPATH+=D:\Qt\Qt5.4.1

阳光柠檬_的技术笔记 4861

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

quazip使用,小白也能看懂(在Qt中使用)

在Qt中使用quazip压缩文件

m0_74022323的博客 2030

Qt QuaZip 从共享内存读了的文件,内存压缩 ,写成文件

使用。

q610098308的专栏 743
上一篇: QML 状态机 与 动画
下一篇: QML Component 与 Loader 结合动态加载组件
cpp_learners
博客等级 码龄7年 1526粉丝 274原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cpp_learners

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值