Qt 压缩/解压文件

前面讲了很多Qt的文件操作,文件操作自然就包括压缩与解压缩文件了,正好最近项目里要用到压缩以及解压缩文件,所以就研究了一下Qt如何压缩与解压缩文件。

QZipReader/QZipWriter

QZipReader 和 QZipWriter 类提供了用于读取和写入 ZIP 格式文件的功能,这个是qt自带的,试了一下个人感觉并不好用。

首先QZipReader/QZipWriter是在Qt5.14之后才引入的,而且使用需要用到gui-private这个模块,搜了一下,在 Qt 中,gui-private 模块是 Qt 框架中的一个私有模块,通常不是为公共使用而设计的。该模块包含了一些 Qt GUI 框架内部使用的实现细节、私有接口和工具类,而不是为外部开发者提供的公共 API。一般来说,Qt 将其功能模块划分为公共模块和私有模块。公共模块包含了开发者可以直接使用的公共 API,而私有模块则包含了框架内部的实现细节和工具类,这些类通常不应该被外部开发者直接使用。所以才不推荐使用。直接看代码:

首先pro文件包含对应模块:

QT +=gui-private

头文件包含:

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

压缩函数:

/*** @brief 压缩文件* @param fileNames 需要压缩的文件绝对路径* @param path 压缩后的文件的绝对路径*/
void zip_compress(const QStringList &fileNames, const QString &path) {QZipWriter *zipWriter = new QZipWriter(path);foreach (const QString &fileName, fileNames) {if (fileName.isEmpty()) continue;QFileInfo fileInfo(fileName);if (!fileInfo.exists()) continue;QFile file(fileName);if (!file.open(QIODevice::ReadOnly)) continue;zipWriter->addFile(fileInfo.fileName(), file.readAll());file.close();}zipWriter->close();if (zipWriter) {delete zipWriter;zipWriter = nullptr;}
}

解压函数:

/*** @brief 解压缩文件* @param fileName 需要解压缩的文件* @param path 解压后文件存放的目录*/
void zip_decompress(const QString &fileName, const QString &path) {if (fileName.isEmpty()) {return;}QFileInfo fileInfo(fileName);if (!fileInfo.exists()) {return;}QZipReader *reader = new QZipReader(fileName);foreach (const QZipReader::FileInfo &info, reader->fileInfoList()) {if (!info.isDir) {QString filePath =QDir::cleanPath(path + QDir::separator() + info.filePath);QFile file(filePath);if (!file.open(QIODevice::WriteOnly)) {continue;}file.write(reader->fileData(info.filePath));file.close();} else {QString dirName =QDir::cleanPath(path + QDir::separator() + info.filePath);QDir dir(dirName);if (!dir.exists()) dir.mkdir(dirName);}}reader->close();if (reader) {delete reader;reader = nullptr;}
}

7z

常用的解压软件比较多,例如winrar、7z、bandzip等等,其中7z是支持命令行形式的,详细命令可以看一下这两篇文章:

7z 命令行详解_7z命令-CSDN博客

前面我的这篇文章:Qt外部调用进程类QProcess的使用_windows qt 调用其它进程-CSDN博客 

就介绍过Qt如何通过QProcess调用外部进程,所以可以先安装7z然后使用QProcess调用7z应用程序,通过传参形式来压缩和解压缩文件,直接看代码:

压缩函数:

/*** @brief z7_compress 压缩函数* @param fileNames 需要压缩的文件的绝对路径* @param path 压缩后生成的压缩文件的绝对路径*/
void z7_compress(const QStringList &fileNames, const QString &path) {QProcess process(0);QStringList args;args.append("a");args.append(path);args.append(fileNames);args.append("-mx=3");process.start("7z.exe", args);//注意7z.exe的路径process.waitForStarted();process.waitForFinished();
}

解压缩函数: 

/*** @brief z7_decompress 解压缩函数* @param fileName 需要解压缩的压缩包路径* @param path 解压缩后生成的目录*/
void z7_decompress(const QString &fileName, const QString &path) {QProcess process(0);QStringList args;args.append("x");args.append(fileName);args.append("-o" + path);args.append("-aoa");process.start("7z.exe", args);//注意7z.exe的路径process.waitForStarted();process.waitForFinished();
}

ZLib

Qt压缩和解压缩文件也可以借助第三方库,zlib或者libzip,这里只介绍zlib。libzip有兴趣的也可以自己下去研究。

zlib 是一个开源的数据压缩库,广泛用于许多应用程序和系统中。以下是关于 zlib 的详细介绍:

  1. 功能

    • zlib 库提供了数据压缩和解压缩的功能,支持使用 DEFLATE 算法进行数据压缩。
    • zlib 提供了简单的 API,易于集成到各种应用程序中。
    • zlib 还支持在压缩数据中添加校验和,以确保数据的完整性。
  2. 特点

    • 高效性:zlib 使用 DEFLATE 算法进行数据压缩,具有较高的压缩比和压缩速度。
    • 跨平台性:zlib 可以在各种操作系统上运行,包括 Windows、Linux、macOS 等。
    • 开源性:zlib 是一个开源库,使用 zlib 的应用程序可以遵循 zlib 的开源许可协议。
  3. 使用场景

    • zlib 可用于在应用程序中对数据进行压缩,减小数据传输和存储的大小。
    • zlib 还可用于处理压缩文件格式,如 ZIP、PNG、HTTP 的 gzip 压缩等。
    • zlib 也常用于实时数据流的压缩,如网络传输中的数据压缩。
  4. API

    • zlib 提供了一组简单的 C 函数来进行数据压缩和解压缩,如 compress()uncompress()deflate()inflate() 等。
    • zlib 还提供了一些工具函数和数据结构,如 z_stream 结构体用于维护压缩和解压缩的状态。

首先需要下载zlib源码,zlib官网,下载之后解压然后准备编译:

使用Cmake:

 注意cmake对应vs,我电脑vs装的是VS2022,所以我这里选的是2022。

然后先Configure再Generate等待完成:

然后进入生成目录使用VS打开对应工程文件:

编译生成:

 注意debug和relase版本以及平台。

对应生成的库文件以及导入库文件:

 建立这样的一个文件目录结构,然后准备在代码中使用:

注意:zconf.h这个文件在cmake生成的文件目录里面 。dll动态库文件放在可执行文件同级目录下。

在工程文件中引入对应头文件以及库文件:

#引入zlib头文件和库
INCLUDEPATH += $PWD/zlib/includewin32 {LIBS += -L$$PWD/zlib/libCONFIG(release, debug|release) {LIBS += -lzlib}CONFIG(debug, debug|release) {LIBS += -lzlibd}
}

试一下zlib的压缩以及解压字符串函数。

压缩字符串:

static QByteArray compress(const QByteArray &data) {z_stream zs;memset(&zs, 0, sizeof(zs));if (deflateInit(&zs, Z_BEST_COMPRESSION) != Z_OK) { return QByteArray(); }zs.next_in = (Bytef *)data.constData();zs.avail_in = data.size();int ret;char outbuffer[32768];QByteArray outstring;do {zs.next_out = reinterpret_cast<Bytef *>(outbuffer);zs.avail_out = sizeof(outbuffer);ret = deflate(&zs, Z_FINISH);if (outstring.size() < zs.total_out) {outstring.append(outbuffer, zs.total_out - outstring.size());}} while (ret == Z_OK);deflateEnd(&zs);if (ret != Z_STREAM_END) { return QByteArray(); }return outstring;
}


解压缩字符串:

static QByteArray decompress(const QByteArray &data) {z_stream zs;memset(&zs, 0, sizeof(zs));if (inflateInit(&zs) != Z_OK) { return QByteArray(); }zs.next_in = (Bytef *)data.constData();zs.avail_in = data.size();int ret;char outbuffer[32768];QByteArray outstring;do {zs.next_out = reinterpret_cast<Bytef *>(outbuffer);zs.avail_out = sizeof(outbuffer);ret = inflate(&zs, 0);if (outstring.size() < zs.total_out) {outstring.append(outbuffer, zs.total_out - outstring.size());}} while (ret == Z_OK);inflateEnd(&zs);if (ret != Z_STREAM_END) { return QByteArray(); }return outstring;
}

测试压缩一个长字符串:

zlib的压缩与解压缩文件目前我网上搜的只能压缩和解压缩单个的,多个的目前没有找到,简单看一下压缩和解压缩的函数。

bool compress(const QString &fileName, const QString &zipFileName) {QFile inputFile(fileName);if (!inputFile.open(QIODevice::ReadOnly)) { return false; }gzFile zipFile = gzdopen(inputFile.handle(), "wb");if (!zipFile) { return false; }char buffer[1024];int bytesRead;while ((bytesRead = inputFile.read(buffer, sizeof(buffer))) > 0) {gzwrite(zipFile, buffer, bytesRead);}gzclose(zipFile);  // 关闭文件句柄inputFile.close(); // 关闭输入文件return true;
}bool decompress(const QString &zipFileName, const QString &fileName) {QFile inputFile(zipFileName);if (!inputFile.open(QIODevice::ReadOnly)) { return false; }QFile outputFile(fileName);if (!outputFile.open(QIODevice::WriteOnly)) { return false; }gzFile zipFile = gzdopen(inputFile.handle(), "rb");if (!zipFile) { return false; }char buffer[1024];int bytesRead;while ((bytesRead = gzread(zipFile, buffer, sizeof(buffer))) > 0) {if (outputFile.write(buffer, bytesRead) != bytesRead) { return false; }}gzclose(zipFile);inputFile.close();outputFile.close();return true;
}

那如果要压缩多个文件怎么办?这里可以使用QuaZip。

QuaZip

QuaZIP 是一个用于 Qt 框架的 C++ 库,它提供了对 ZIP 归档文件的读写功能。QuaZIP 是基于 zlib 和 minizip 库的封装,使得在 Qt 项目中可以方便地处理 ZIP 文件。也就是说QuaZIP是基于zlib的,使用QuaZIP的前提是已经编译好了zlib,zlib的编译前面已经讲了。这里直接开始讲QuaZIP的编译与使用。

首先下载QuaZIP,QuaZIP官网。下载之后进行解压:

可以看到里面有pro文件也有vs工程文件也有CMakeLists.txt文件,我们直接使用QtCreator来进行编译。首先因为QuaZIP依赖zlib,所以把刚刚编译的zlib文件放进来:

这个文件夹结构跟刚刚一样。

我们只编译库,所以进到这个目录:

 

把对应头文件放进来:

对应工程文件添加引入zlib:

然后开始编译生成对应debug和release版的库文件和导入库文件:

同样方法创建一个quazip文件夹,然后拷贝对应头文件以及导入库文件:

新建一个工程,将对应quazip文件放进工程文件夹内容,然后对应pro文件引入quazip头文件以及相关导入库文件:

INCLUDEPATH += $PWD/quazip/includewin32 {LIBS += -L$$PWD/quazip/libCONFIG(release, debug|release) {LIBS += -lquazip}CONFIG(debug, debug|release) {LIBS += -lquazipd}
}

对应动态库文件放入到可执行文件同级目录下:

注意:别忘了zlib的库文件,我测试用的debug版,所以理论上只放debug版对应zlib和QuaZIP的库文件就够了。

QuaZIP压缩和解压缩文件已经封装好了方法,比如将指定目录内的所有子目录以及文件压缩到指定压缩包内方法:

  \param fileCompressed The name of the archive.\param dir The directory to compress.\param recursive Whether to pack the subdirectories as well, orjust regular files.\return true if success, false otherwise.*/static bool compressDir(QString fileCompressed, QString dir = QString(), bool recursive = true);

对应的解压方法:

/**\param fileCompressed The name of the archive.\param dir The directory to extract to, the current directory ifleft empty.\return The list of the full paths of the files extracted, empty on failure.*/static QStringList extractDir(QString fileCompressed, QString dir = QString());/// Get the file list.

写一个简单的测试程序。

界面ui:

头文件:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACEclass MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_openDir_clicked();void on_compress_clicked();void on_selectZip_clicked();void on_decompress_clicked();private:Ui::MainWindow *ui;
};
#endif  // MAINWINDOW_H

源文件: 

#include "mainwindow.h"
#include "quazip/include/JlCompress.h"
#include "ui_mainwindow.h"#include <QDebug>
#include <QDir>
#include <QFileDialog>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);
}MainWindow::~MainWindow() { delete ui; }void MainWindow::on_openDir_clicked() {QString dirPath =QFileDialog::getExistingDirectory(nullptr, QString(), QString());ui->dePath->setText(dirPath);
}void MainWindow::on_compress_clicked() {if (ui->dePath->text().isEmpty()) return;QDir deDir(ui->dePath->text());if (!deDir.exists()) return;if (deDir.isEmpty()) return;QString zipFileName = QDir::cleanPath(deDir.absolutePath() + QDir::separator() + deDir.dirName() + ".zip");bool r = JlCompress::compressDir(zipFileName, deDir.absolutePath());if (r)qDebug() << "compress success";elseqDebug() << "compress fail";
}void MainWindow::on_selectZip_clicked() {QString zipFileName = QFileDialog::getOpenFileName(nullptr, QString(), QString(), "Code Files (*.zip *.7z)");if (zipFileName.isEmpty()) return;ui->zipPath->setText(zipFileName);
}void MainWindow::on_decompress_clicked() {if (ui->zipPath->text().isEmpty()) return;QString zipFileName = ui->zipPath->text();if (!QFile::exists(zipFileName)) return;QFileInfo zipFileInfo(zipFileName);QString deDirPath =QDir::cleanPath(zipFileInfo.absolutePath() + QDir::separator() +zipFileInfo.completeBaseName());QDir deDir(deDirPath);if (!deDir.exists()) QDir().mkpath(deDirPath);QStringList fileList = JlCompress::extractDir(zipFileInfo.absoluteFilePath(),deDir.absolutePath());if (!fileList.isEmpty())qDebug() << "decompress success";elseqDebug() << "decompress fail";
}

测试一下:

没有问题,这个测试文件的代码我会上传,仅供参考,我编译的zlib以及QuaZIP的库文件也在里面,建议自己编译,因为平台或者编译软件可能与我不同,我的环境是Windows,VS2022,Qt5.15.2。

其他相关压缩以及解压缩这里就不做介绍了,有兴趣的可以下去自己研究一下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/284543.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringCloud Gateway工作流程

Spring Cloud Gateway的工作流程 具体的流程&#xff1a; 用户发送请求到网关 请求断言&#xff0c;用户请求到达网关后&#xff0c;由Gateway Handler Mapping&#xff08;网关处理器映射&#xff09;进行Predicates&#xff08;断言&#xff09;&#xff0c;看一下哪一个符合…

2024年C语言最新经典面试题汇总(11-20)

C语言文章更新目录 C语言学习资源汇总&#xff0c;史上最全面总结&#xff0c;没有之一 C/C学习资源&#xff08;百度云盘链接&#xff09; 计算机二级资料&#xff08;过级专用&#xff09; C语言学习路线&#xff08;从入门到实战&#xff09; 编写C语言程序的7个步骤和编程…

深度学习 线性神经网络(线性回归 从零开始实现)

介绍&#xff1a; 在线性神经网络中&#xff0c;线性回归是一种常见的任务&#xff0c;用于预测一个连续的数值输出。其目标是根据输入特征来拟合一个线性函数&#xff0c;使得预测值与真实值之间的误差最小化。 线性回归的数学表达式为&#xff1a; y w1x1 w2x2 ... wnxn …

LeetCode每日一题——统计桌面上的不同数字

统计桌面上的不同数字OJ链接&#xff1a;2549. 统计桌面上的不同数字 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 思路&#xff1a; 这是一个很简单的数学问题&#xff1a; 当n 5时&#xff0c;因为n % 4 1&#xff0c;所以下一天4一定会被放上桌面 当n 4…

TnT-LLM: Text Mining at Scale with Large Language Models

TnT-LLM: Text Mining at Scale with Large Language Models 相关链接&#xff1a;arxiv 关键字&#xff1a;Large Language Models (LLMs)、Text Mining、Label Taxonomy、Text Classification、Prompt-based Interface 摘要 文本挖掘是将非结构化文本转换为结构化和有意义的…

QT(C++)-error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“2”不匹配值“0”

1、项目场景&#xff1a; 在VS中采用QT&#xff08;C&#xff09;调试时&#xff0c;出现error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“2”不匹配值“0”错误 2、解决方案&#xff1a; 在“解决方案资源管理器”中选中出现此类BUG的项目&#xff0c;右键-…

【NLP笔记】预训练+微调范式之OpenAI Transformer、ELMo、ULM-FiT、Bert..

文章目录 OpenAI TransformerELMoULM-FiTBert基础结构Embedding预训练&微调 【原文链接】&#xff1a; BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding 【本文参考链接】 The Illustrated BERT, ELMo, and co. (How NLP Cracked Tra…

提面 | 面试抽题

学习到更新日期面试抽题-1.2案例分析的思维本质2024-3-23 1提面抽屉论述问题的分类 1.1案例分析占总论 1.2案例分析的思维本质

计算机网络相关

OSI七层模型 各层功能&#xff1a; TCP/IP四层模型 应用层 传输层 网络层 网络接口层 访问一个URL的全过程 在浏览器中输入指定网页的 URL。 浏览器通过 DNS 协议&#xff0c;获取域名对应的 IP 地址。 浏览器根据 IP 地址和端口号&#xff0c;向目标服务器发起一个 TCP…

【进阶五】Python实现SDVRP(需求拆分)常见求解算法——离散粒子群算法(DPSO)

基于python语言&#xff0c;采用经典离散粒子群算法&#xff08;DPSO&#xff09;对 需求拆分车辆路径规划问题&#xff08;SDVRP&#xff09; 进行求解。 目录 往期优质资源1. 适用场景2. 代码调整3. 求解结果4. 代码片段参考 往期优质资源 经过一年多的创作&#xff0c;目前已…

linux文本三剑客 --- grep、sed、awk

1、grep grep&#xff1a;使用正则表达式搜索文本&#xff0c;将匹配的行打印出来&#xff08;匹配到的标红&#xff09; 命令格式&#xff1a;grep [option] pattern file <1> 命令参数 -A<显示行数>&#xff1a;除了显示符合范本样式的那一列之外&#xff0c;并…

C语言中的联合体和枚举

联合体 联合体的创建 联合体的关键字是union union S {char a;int i; };除了关键字和结构体不一样之外&#xff0c;联合体的创建语法形式和结构体的很相似&#xff0c;如果不熟悉结构体的创建&#xff0c;可以看一下我上一篇的博客关于结构体知识的详解。 联合体的特点 联合…

Personal Website

Personal Website Static Site Generators hexo hugo jekyll Documentation Site Generator gitbook vuepress vitepress docsify docute docusaurus Deployment 1. GitHub Pages 2. GitLab Pages 3. vercel 4. netlify Domain 域名注册 freessl 域名解析域名…

【GUI】自动化办公

目录 一、GUI介绍 二、环境安装 三、鼠标移动操作 四、鼠标点击操作 五、拖动鼠标 六、鼠标滚动操作 七、屏幕快照&图像识别基础 7.1 屏幕快照&#xff08;截图&#xff09; 7.2 图像识别 八、键盘控制 一、GUI介绍 GUI自动化就是写程序直接控制键盘和鼠标。这些…

电脑如何关闭自启动应用?cmd一招解决问题

很多小伙伴说电脑刚开机就卡的和定格动画似的&#xff0c;cmd一招解决问题&#xff1a; CtrlR打开cmd,输入&#xff1a;msconfig 进入到这个界面&#xff1a; 点击启动&#xff1a; 打开任务管理器&#xff0c;禁用不要的自启动应用就ok了

【prometheus-operator】k8s监控集群外redis

1、部署exporter GitHub - oliver006/redis_exporter: Prometheus Exporter for Redis Metrics. Supports Redis 2.x, 3.x, 4.x, 5.x, 6.x, and 7.x redis_exporter-v1.57.0.linux-386.tar.gz # 解压 tar -zxvf redis_exporter-v1.57.0.linux-386.tar.gz # 启动 nohup ./redi…

SpringCloud-记

目录 什么是SpringCloud 什么是微服务 SpringCloud的优缺点 SpringBoot和SpringCloud的区别 RPC 的实现原理 RPC是什么 eureka的自我保护机制 Ribbon feigin优点 Ribbon和Feign的区别 什么是SpringCloud Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发…

力扣面试150 阶乘后的零 数论 找规律 质因数

Problem: 172. 阶乘后的零 思路 &#x1f468;‍&#x1f3eb; 大佬神解 一个数末尾有多少个 0 &#xff0c;取决于这个数 有多少个因子 10而 10 可以分解出质因子 2 和 5而在阶乘种&#xff0c;2 的倍数会比 5 的倍数多&#xff0c;换而言之&#xff0c;每一个 5 都会找到一…

AI时代Python金融大数据分析实战:ChatGPT让金融大数据分析插上翅膀

❤️作者主页&#xff1a;小虚竹 ❤️作者简介&#xff1a;大家好,我是小虚竹。2022年度博客之星评选TOP 10&#x1f3c6;&#xff0c;Java领域优质创作者&#x1f3c6;&#xff0c;CSDN博客专家&#x1f3c6;&#xff0c;华为云享专家&#x1f3c6;&#xff0c;掘金年度人气作…

电脑照片分辨率怎么调?这款dpi修改工具好用

许多考试平台在上传证件照片的时候&#xff0c;大多都会对图片分辨率有具体要求&#xff0c;但是如果遇上手上的图片分辨率达不到要求&#xff0c;那么怎么改图片分辨率呢&#xff1f;可以利用专业的dpi修改工具来处理&#xff0c;比如今天分享的就是一个在线修改图片分辨率的方…