• C++QT实现压缩文件、文件夹和解压缩操作


    一、前言

    QZipWriter是用来压缩文件的类,需要在安装Qt是选择Sources源码安装。否则,无法使用QZipWriter。

     

    1. QZipWriter函数说明
    1.1 构造方法:

    1. QZipWriter(const QString &fileName, QIODevice::OpenMode mode = (QIODevice::WriteOnly | QIODevice::Truncate) );
    2. QZipWriter(QIODevice *device);

    fileName:保存zip文件的地址。

    QIODevice 是 QFile 的父类,因此在构造 QZipWriter类的对象时,可以传递一个 QFile 类的对象。

    本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QT嵌入式开发,Quick模块等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

    1.2 设置压缩权限:

    1. enum CompressionPolicy {
    2. AlwaysCompress,
    3. NeverCompress,
    4. AutoCompress
    5. };
    6. void setCompressionPolicy(CompressionPolicy policy);
    7. CompressionPolicy compressionPolicy() const;


    1.3 添加文件:

     void addFile(const QString &fileName, const QByteArray &data);


    1.4 添加目录:

    void addDirectory(const QString &dirName);


    如果需要将文件压缩到lib目录下,那么可以这样操作:

    1. writer->addDirectory("lib");
    2. writer->addFile("lib/" + fileName, const QByteArray &data);

    这样压缩,就可以在压缩包当中看到lib目录,并且文件在lib目录下。

    二、实现方式

    通过Qt自带的库来实现,使用多线程方式,通过信号和槽来触发压缩与解压缩,并将压缩和解压缩结果回传过来。
    使用的类:

    1. #include "QtGui/private/qzipreader_p.h"
    2. #include "QtGui/private/qzipwriter_p.h"

    三、具体步骤

    1、在.pro文件中添加模块gui-private

    QT       += core gui gui-private

    2、通过QObject方式创建多线程实现压缩与解压缩类

    CompreDecompreFileThread.h

    1. #ifndef COMPREDECOMPREFILETHREAD_H
    2. #define COMPREDECOMPREFILETHREAD_H
    3. #include
    4. #include "QtGui/private/qzipreader_p.h"
    5. #include "QtGui/private/qzipwriter_p.h"
    6. #include
    7. #include
    8. #include
    9. #include
    10. class CompreDecompreFileThread : public QObject
    11. {
    12. Q_OBJECT
    13. public:
    14. typedef enum
    15. {
    16. success,
    17. failed,
    18. running
    19. }ResultE;
    20. signals:
    21. void compression_res_signal(ResultE res,quint8 progress,QString remarks = nullptr);
    22. void decompression_res_signal(ResultE res,quint8 progress,QString remarks = nullptr);
    23. public slots:
    24. /*
    25. * 压缩文件
    26. */
    27. void compression_file_run(QString srcPath,QString destPath);
    28. /*
    29. * 解压文件
    30. */
    31. void decompression_file_run(QString srcPath,QString destPath);
    32. public:
    33. explicit CompreDecompreFileThread(QObject *parent = nullptr);
    34. private:
    35. /*
    36. * 遍历压缩文件
    37. */
    38. QFileInfoList ergodic_compression_file(QZipWriter *writer,QString rootPath,QString filePath);
    39. private:
    40. QZipWriter *zipWriter = nullptr;
    41. QZipReader *zipReader = nullptr;
    42. };
    43. #endif // COMPREDECOMPREFILETHREAD_H

    CompreDecompreFileThread.cpp

    1. #include "compredecomprefilethread.h"
    2. #include <QDebug>
    3. #include <QIODevice>
    4. CompreDecompreFileThread::CompreDecompreFileThread(QObject *parent)
    5. : QObject{parent}
    6. {
    7. qRegisterMetaType<ResultE>("ResultE");
    8. }
    9. QFileInfoList CompreDecompreFileThread::ergodic_compression_file(QZipWriter *writer, QString rootPath, QString filePath)
    10. {
    11. QDir dir(filePath); //遍历各级子目录
    12. QDir fileDir(filePath); //遍历子目录中所有文件
    13. //先遍历文件夹 添加进widget
    14. QFileInfoList fileList=dir.entryInfoList(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
    15. QFileInfoList folderList = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); //获取当前所有目录 QDir::Dirs 0x001 列出目录;
    16. for(int i = 0; i != folderList.size(); i++) //自动递归添加各目录到上一级目录
    17. {
    18. QString namepath = folderList.at(i).absoluteFilePath(); //获取路径
    19. QFileInfo folderinfo= folderList.at(i);
    20. QString name=folderinfo.fileName(); //获取目录名
    21. QStringList list = folderinfo.absoluteFilePath().split(rootPath);
    22. //qDebug()<<"Dir:"<<folderinfo.absoluteFilePath().remove(list.at(0));
    23. writer->addDirectory(folderinfo.absoluteFilePath().remove(list.at(0)));
    24. QFileInfoList child_file_list = ergodic_compression_file(writer,rootPath,namepath); //进行递归 递归这个文件夹
    25. fileList.append(child_file_list);
    26. // file_list.append(name);
    27. }
    28. /*添加path路径文件*/
    29. fileDir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks); //获取当前所有文件
    30. fileDir.setSorting(QDir::Name);
    31. QFileInfoList _fileList = fileDir.entryInfoList();
    32. for (int i = 0; i < _fileList.size(); ++i) //将当前目录中所有文件添加到treewidget中
    33. {
    34. QFileInfo fileInfo = _fileList.at(i);
    35. QFile file(fileInfo.absoluteFilePath());
    36. if(file.open(QIODevice::ReadOnly))
    37. {
    38. QStringList list = fileInfo.absoluteFilePath().split(rootPath);
    39. //qDebug()<<"File:"<<fileInfo.absoluteFilePath().remove(list.at(0));
    40. writer->addFile(fileInfo.absoluteFilePath().remove(list.at(0)),file.readAll());
    41. file.close();
    42. }
    43. }
    44. return fileList;
    45. }
    46. void CompreDecompreFileThread::compression_file_run(QString srcPath, QString destPath)
    47. {
    48. qDebug()<<QThread::currentThreadId();
    49. if(srcPath == nullptr || destPath == nullptr)
    50. {
    51. emit compression_res_signal(ResultE::failed,100,tr("路径为空!"));
    52. return;
    53. }
    54. QFileInfo fileDistInfo(destPath);
    55. if(fileDistInfo.isFile()) //目的路径不能为文件名
    56. {
    57. emit compression_res_signal(ResultE::failed,100,tr("路径不能为文件!"));
    58. return;
    59. }
    60. QFileInfo fileInfo(srcPath);
    61. if(fileInfo.isFile())//压缩的是一个文件
    62. {
    63. QString saveFileName = destPath+"/"+fileInfo.baseName()+".zip";
    64. qDebug()<<"saveFileName:"<<saveFileName;
    65. this->zipWriter = new QZipWriter(saveFileName);
    66. QFile file(srcPath);
    67. if(!file.open(QIODevice::ReadOnly))
    68. {
    69. emit compression_res_signal(ResultE::failed,100,tr("文件打开失败!"));
    70. return;
    71. }
    72. emit compression_res_signal(ResultE::running,50,tr("正在压缩中..."));
    73. this->zipWriter->addFile(file.fileName(),file.readAll());
    74. this->zipWriter->close();
    75. delete this->zipWriter;
    76. this->zipWriter = nullptr;
    77. emit compression_res_signal(ResultE::running,100,tr("正在压缩中..."));
    78. emit compression_res_signal(ResultE::success,100,tr("压缩完成!"));
    79. }
    80. else //压缩的是一个文件夹
    81. {
    82. QString folderStr = srcPath.mid(srcPath.lastIndexOf("/")).remove("/");
    83. if(folderStr == nullptr)
    84. {
    85. emit compression_res_signal(ResultE::failed,100,tr("压缩文件路径错误!"));
    86. return;
    87. }
    88. emit compression_res_signal(ResultE::running,50,tr("正在压缩中..."));
    89. QString saveFileName = destPath+"/"+folderStr+".7z";
    90. qDebug()<<"saveFileName:"<<saveFileName;
    91. this->zipWriter = new QZipWriter(saveFileName);
    92. this->zipWriter->addDirectory(folderStr);
    93. this->ergodic_compression_file(this->zipWriter,folderStr,srcPath);
    94. delete this->zipWriter;
    95. this->zipWriter = nullptr;
    96. emit compression_res_signal(ResultE::running,100,tr("正在压缩中..."));
    97. emit compression_res_signal(ResultE::success,100,tr("压缩完成!"));
    98. }
    99. }
    100. void CompreDecompreFileThread::decompression_file_run(QString srcPathAndName, QString destPath)
    101. {
    102. qDebug()<<QThread::currentThreadId();
    103. if(srcPathAndName == nullptr || destPath == nullptr)
    104. {
    105. emit decompression_res_signal(ResultE::failed,100,tr("路径为空!"));
    106. return;
    107. }
    108. QFileInfo destInfo(destPath);
    109. if(destInfo.isFile()||!destInfo.exists())
    110. {
    111. emit decompression_res_signal(ResultE::failed,100,tr("目的路径异常!"));
    112. return;
    113. }
    114. QFileInfo fileInfo(srcPathAndName);
    115. if(!fileInfo.isFile() || fileInfo.suffix() !="zip")
    116. {
    117. emit decompression_res_signal(ResultE::failed,100,tr("压缩文件为空!"));
    118. return;
    119. }
    120. emit decompression_res_signal(ResultE::running,50,tr("正在解压缩..."));
    121. this->zipReader = new QZipReader(srcPathAndName);
    122. bool res = this->zipReader->extractAll(destPath);
    123. emit decompression_res_signal(ResultE::running,100,tr("正在解压缩..."));
    124. if(res) //解压缩成功
    125. {
    126. emit decompression_res_signal(ResultE::success,100,tr("解压缩完成!"));
    127. }
    128. else
    129. {
    130. emit decompression_res_signal(ResultE::failed,100,tr("解压缩失败!"));
    131. }
    132. this->zipReader->close();
    133. delete this->zipReader;
    134. this->zipReader = nullptr;
    135. }

    mainwindow.h

    1. #ifndef MAINWINDOW_H
    2. #define MAINWINDOW_H
    3. #include
    4. #include "QtGui/private/qzipreader_p.h"
    5. #include "QtGui/private/qzipwriter_p.h"
    6. #include
    7. #include
    8. #include
    9. #include "compredecomprefilethread.h"
    10. #include
    11. QT_BEGIN_NAMESPACE
    12. namespace Ui { class MainWindow; }
    13. QT_END_NAMESPACE
    14. class MainWindow : public QMainWindow
    15. {
    16. Q_OBJECT
    17. signals:
    18. void compress_signal(QString srcPath,QString destPath);
    19. void decompress_signal(QString srcPath,QString destPath);
    20. public:
    21. MainWindow(QWidget *parent = nullptr);
    22. ~MainWindow();
    23. private slots:
    24. void on_btnZip_clicked();
    25. void on_btnUnZip_clicked();
    26. void compress_res_slot(CompreDecompreFileThread::ResultE res,quint8 progress,QString remarks = nullptr);
    27. void decompress_res_slot(CompreDecompreFileThread::ResultE res,quint8 progress,QString remarks = nullptr);
    28. private:
    29. Ui::MainWindow *ui;
    30. CompreDecompreFileThread *compreDecompreFileThread;
    31. QThread *compreDecompreFileMainThread;
    32. };
    33. #endif // MAINWINDOW_H

    mainwindow.cpp

    1. #include "mainwindow.h"
    2. #include "ui_mainwindow.h"
    3. #include <QDebug>
    4. MainWindow::MainWindow(QWidget *parent)
    5. : QMainWindow(parent)
    6. , ui(new Ui::MainWindow)
    7. {
    8. ui->setupUi(this);
    9. compreDecompreFileThread = new CompreDecompreFileThread;
    10. compreDecompreFileMainThread = new QThread;
    11. compreDecompreFileThread->moveToThread(compreDecompreFileMainThread);
    12. compreDecompreFileMainThread->start();
    13. connect(this,&MainWindow::compress_signal,compreDecompreFileThread,&CompreDecompreFileThread::compression_file_run);
    14. connect(this,&MainWindow::decompress_signal,compreDecompreFileThread,&CompreDecompreFileThread::decompression_file_run);
    15. connect(compreDecompreFileThread,&CompreDecompreFileThread::compression_res_signal,this,&MainWindow::compress_res_slot);
    16. connect(compreDecompreFileThread,&CompreDecompreFileThread::decompression_res_signal,this,&MainWindow::decompress_res_slot);
    17. qDebug()<<QThread::currentThreadId();
    18. }
    19. MainWindow::~MainWindow()
    20. {
    21. delete ui;
    22. }
    23. //bool zipReader(QString zipPath="test.zip", QString zipDir="")
    24. //{
    25. // QDir tempDir;
    26. // if(!tempDir.exists(zipDir)) tempDir.mkpath(zipDir);
    27. // QZipReader reader(zipPath);
    28. // return reader.extractAll(zipDir);
    29. //}
    30. void MainWindow::on_btnZip_clicked()
    31. {
    32. QString filePath = QApplication::applicationDirPath()+"/test";
    33. QString zipPath = QApplication::applicationDirPath();
    34. emit compress_signal(filePath,zipPath);
    35. }
    36. void MainWindow::on_btnUnZip_clicked()
    37. {
    38. QString filePath = QApplication::applicationDirPath()+"/test.zip";
    39. QString zipPath = QApplication::applicationDirPath()+"/unTest";
    40. qDebug()<<"filePath:"<<filePath<<"zipPath:"<<zipPath;
    41. emit decompress_signal(filePath,zipPath);
    42. }
    43. void MainWindow::compress_res_slot(CompreDecompreFileThread::ResultE res, quint8 progress, QString remarks)
    44. {
    45. qDebug()<<"Com:"<<" res:"<<res<<" progress:"<<progress<<" remarks:"<<remarks;
    46. }
    47. void MainWindow::decompress_res_slot(CompreDecompreFileThread::ResultE res, quint8 progress, QString remarks)
    48. {
    49. qDebug()<<"deCom:"<<" res:"<<res<<" progress:"<<progress<<" remarks:"<<remarks;
    50. }

    mainwindow.ui

    本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QT嵌入式开发,Quick模块等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

  • 相关阅读:
    每日五道java面试题之spring篇(二)
    正确理解党籍和党龄;入党和转正时间
    如何用client-go获取k8s因硬盘容量、cpu、内存、gpu资源不够引起的错误信息?
    vue2.0 双向绑定原理分析及简单实现
    Go - 用户服务和Web服务
    HTML快速入门
    EasyGBS播放器优化:设备通道视频播放出现跳屏问题的修复
    RabbitMQ(九)【内存磁盘的监控】
    【kylin/ubuntu 】离线命令行基本操作
    开发上门按摩系统对技师如何管理,薪资结构怎么设计
  • 原文地址:https://blog.csdn.net/m0_60259116/article/details/127888768