Qt 实现压缩文件、文件夹和解压缩操作zip

2023-11-20

一、实现方式

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

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

二、环境准备

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

QT       += core gui gui-private

若未cmake工程,需要在CMakeList.txt中添加

includeinclude_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS}))

三、实现示例

#include <QFileInfoList>
#include <QDir>
#include <QFileInfo>

#define	FILE_MAX_SIZE 1024

QFileInfoList ergodic_compression_file(QZipWriter *writer, const QString& rootPath, QString dirPath)
{
	QDir crrDir(dirPath);
	///解压失败的文件
	QFileInfoList errFileList;

	///添加文件
	QFileInfoList fileList = crrDir.entryInfoList(QDir::Files | QDir::Hidden);
	for (const QFileInfo& fileInfo : fileList)
	{
		QString subFilePath = fileInfo.absoluteFilePath();
		QString zipWithinfilePath = subFilePath.mid(rootPath.size() + 1);

		QFile file(subFilePath);
		qint64 size = file.size() / 1024 / 1024;
		if (!file.open(QIODevice::ReadOnly) || size > FILE_MAX_SIZE)
		{
			///打开文件失败,或者大于1GB导致无法解压的文件
			errFileList.append(fileInfo);
			continue;
		}
		writer->addFile(zipWithinfilePath, file.readAll());
		file.close();
	}

	///添加文件夹
	QFileInfoList folderList = crrDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
	for (const QFileInfo& folderInfo : folderList)
	{
		QString subDirPath = folderInfo.absoluteFilePath();
		QString zipWithinDirPath = subDirPath.mid(rootPath.size() + 1);

		writer->addDirectory(zipWithinDirPath);
		QFileInfoList child_file_list = ergodic_compression_file(writer, rootPath, subDirPath);
		errFileList.append(child_file_list);
	}

	return errFileList;
}

bool compression_zip_file(const QString& selectFile2DirPath, const QString& savePath)
{
	if (selectFile2DirPath.isEmpty() || savePath.isEmpty())
	{
		return false;
	}
	if (!QFile::exists(selectFile2DirPath) || !QFileInfo(savePath).isDir())
	{
		return false;
	}

	if (QFileInfo(selectFile2DirPath).isFile())///压缩的是一个文件
	{
		QString fileName = QFileInfo(selectFile2DirPath).baseName();
		QString writerFilePath = savePath + "/" + fileName + ".zip";

		QFile selectFile(selectFile2DirPath);
		qint64 size = selectFile.size() / 1024 / 1024;
		if (!selectFile.open(QIODevice::ReadOnly) || size > FILE_MAX_SIZE)
		{
			///打开文件失败,或者大于1GB导致无法压缩的文件
			return false;
		}
		QString addFileName = QFileInfo(selectFile2DirPath).fileName();
		QZipWriter writer(writerFilePath);
		writer.addFile(addFileName, selectFile.readAll());
		selectFile.close();
		return true;
	}
	else///压缩的是一个文件夹
	{
		QString zipRootFolder = selectFile2DirPath.mid(selectFile2DirPath.lastIndexOf("/") + 1);
		QString selectDirUpDir = selectFile2DirPath.left(selectFile2DirPath.lastIndexOf("/"));
		QString saveFilePath = savePath + "/" + zipRootFolder + ".zip";

		QZipWriter writer(saveFilePath);
		writer.addDirectory(zipRootFolder);
		QFileInfoList fileList = ergodic_compression_file(&writer, selectDirUpDir, selectFile2DirPath);
		writer.close();
		if (0 == fileList.size())
			return true;
		return false;
	}
}

bool decompression_zip_file(const QString& selectZipFilePath, const QString& savePath)
{
	if (selectZipFilePath.isEmpty() || savePath.isEmpty())
	{
		return false;
	}
	if (!QFileInfo(selectZipFilePath).isFile() || !QFileInfo(savePath).isDir())
	{
		return false;
	}

	bool ret = true;
	QZipReader zipReader(selectZipFilePath);
	QVector<QZipReader::FileInfo> zipAllFiles = zipReader.fileInfoList();
	for (const QZipReader::FileInfo& zipFileInfo : zipAllFiles)
	{
		const QString currDir2File = savePath + "/" + zipFileInfo.filePath;
		if (zipFileInfo.isSymLink)
		{
			QString destination = QFile::decodeName(zipReader.fileData(zipFileInfo.filePath));
			if (destination.isEmpty())
			{
				ret = false;
				continue;
			}

			QFileInfo linkFi(currDir2File);
			if (!QFile::exists(linkFi.absolutePath()))
				QDir::root().mkpath(linkFi.absolutePath());
			if (!QFile::link(destination, currDir2File))
			{
				ret = false;
				continue;
			}
		}
		if (zipFileInfo.isDir)
		{
			QDir(savePath).mkpath(currDir2File);
		}
		if (zipFileInfo.isFile)
		{
			QByteArray dt = zipFileInfo.filePath.toUtf8();
			QString strtmp = QString::fromLocal8Bit(dt);

			QFile currFile(currDir2File);
			if (!currFile.isOpen())
			{
				currFile.open(QIODevice::WriteOnly);
			}
			else {
				ret = false;
				continue;
			}

			qint64 size = zipFileInfo.size / 1024 / 1024;
			if (size > FILE_MAX_SIZE)
			{
				ret = false;
				continue;
			}
			QByteArray byteArr = zipReader.fileData(strtmp);
			currFile.write(byteArr);
			currFile.setPermissions(zipFileInfo.permissions);
			currFile.close();
		}
	}
	zipReader.close();
	return ret;
}

待验证:
1、中文路径,文件名含有中文
2、隐藏文件夹,.dir和…dir,例如:.vs

待完善:
1、保存路径不存在,直接创建
2、单个超大文件的支持(1G以上)
3、当前操作文件回调
4、进度回调

如有错误或不足欢迎评论指出!创作不易,转载请注明出处。如有帮助,记得点赞关注哦(⊙o⊙)
更多内容请关注个人博客:https://blog.csdn.net/qq_43148810

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt 实现压缩文件、文件夹和解压缩操作zip 的相关文章

  • QGroupBox边框

    经过一段时间的搜索后 我发现在组框上设置可见边框的方法是使用 StyleSheet 属性 我补充道 border 2px solid gray 但有几个问题 1 组框内的所有内容也继承此设置 2 边框在标题附近有一个小洞 碎片缺失 Here
  • 将项目添加到自定义组件的布局

    我有一个习惯Footer Component我想在 QML 应用程序的不同位置重用它 Rectangle color gold height 50 anchors bottom parent bottom left parent left
  • Qt + win32 + mingw 上的原生 Windows API 链接问题

    我正在尝试使用 mingw 工具集将本机 Windows API 与 Qt 结合使用 部分功能存在链接问题 会发生什么 这是 mingw 名称修改的错误吗 ifdef Q WS WIN HWND hwnd QWidget winId HDC
  • 在哪里可以找到 Qt 的 dll 的 pdb 文件?

    我正在调试 Qt 应用程序 在哪里可以找到 Qt 的调试 dll 我在windows上使用的是vs2010 它说它需要 Qt 中的许多 dll 的 pdb 文件 从 Qt 5 9 开始 与 Windows 发行版相对应的 PDB 可作为单独
  • QT 中的应用程序->处理消息?

    在 Borland 6 中 我经常使用它来解除程序操作的卡住 Application gt Processmessages 现在 对于 QT 4 8 1 我在这个外国 对我来说 QT 文档中找不到 谁能帮我 在 Qt 中 您可以使用静态函数
  • 如何恢复 QSS 属性的默认系统值?

    如果父级之一将其样式表设置为 Qt QSS 会传播给子级color red 它的所有子级都将应用此样式表 如果你明确设置QLabel color red 那么只有 QLabel 子项会受到关注 如果子项设置自己的值 则可以覆盖子项的样式表c
  • 如何将图标放置到 QLineEdit 上?

    stackoverflow com 网站的右上角有一个带有放大镜头的搜索字段和一个灰色的 搜索 关键字 我想知道是否有可能实现相同的外观QLineEdit 如果是这样那怎么办 QLineEdit lineEdit new QLineEdit
  • QT 中只获取文件而不获取目录?

    当我这样做时 QDir myDir home some location QStringList filesList myDir entryList 它返回该位置内的文件和目录 但我只想要文件 并且这些文件可以具有任意扩展名 有任何想法吗
  • Qt 支持在 QIcon 中为 SVG 着色

    看来 Qt 不支持 SVG 中路径标签上的描边 填充选项
  • 在 QtCreator 中将 OpenCV 2.3 与 Qt 结合使用

    随着 OpenCV 2 3 版本终于发布 我想在我的系统上编译并安装这个最新版本 由于我经常使用 Qt 和 QtCreator 我当然希望能够在我的 Qt 项目中使用它 我已经尝试了几种方法几个小时 但总是出现错误 第一次尝试 使用WITH
  • MAC 上的 QT/C++ - 未设置应用程序图标

    我正在努力解决的奇怪问题 在与我的 pro QT 项目文件相同的文件夹中 我有一个 Resources myIcon png 我试图将其设置为我构建的应用程序的图标 在 OSX 上运行 我阅读了文档 它建议在 pro 文件中添加 ICON
  • 为什么下面的重叠比较总是评估为 true

    我不明白为什么以下代码有警告 指出重叠比较始终评估为真 接下来的语句永远不会被执行 QVariant MainModel data const QModelIndex index int role const if index isVali
  • Qt/c++ 随机字符串生成[重复]

    这个问题在这里已经有答案了 我正在创建一个应用程序 需要生成多个随机字符串 几乎就像一个由一定长度的 ASCII 字符组成的唯一 ID 这些字符混合有大写 小写 数字字符 有没有 Qt 库可以实现这一点 如果没有 在纯 C 中生成多个随机字
  • QTcpSocket 有时不发送数据

    我有两个 QT 应用程序 一个应用程序可以被认为保存了大数据 它每秒向第二个应用程序发送大约 10 KB 的数据块 之前我尝试使用QUdpSocket来传输数据 但由于MTU限制在2 5K左右 并且需要自己分割和重新组合数据 所以我改用QT
  • QTextEdit.find() 在 Python 中不起作用

    演示问题的简单代码 usr bin env python import sys from PyQt4 QtCore import QObject SIGNAL from PyQt4 QtGui import QApplication QTe
  • 加权 Voronoi 的 CGAL 2D APOLLONIUS 图 - 如何生成和获取面和顶点?

    我正在尝试根据阿波罗尼乌斯图生成加权沃罗诺伊 我正在使用 CGAL 库 我找不到如何从 apollonius 获取面和顶点的好例子 我有以下类型定义 typedef double NT typedef CGAL Cartesian lt N
  • QGraphicsScene::clear 不会改变 sceneRect

    我有一个 QGraphicsScene 场景 和 QGraphicsView graphicsView 我有一个画图的方法 当我需要重绘所有图形时 我调用这个方法 一切都好 但我意识到 scene gt clear 不会改变 sceneRe
  • Qt 文件对话框默认后缀不起作用

    我将以下代码用于 QtQuick Dialogs 1 3 和 Qt 5 10 0 下 filedialog 的新属性 我使用 Qt Creator 5 10 默认套件构建它 import QtQuick 2 10 import QtQuic
  • 如何创建用于 QML 的通用对象模型?

    我想知道是否有任何宏或方法如何将 Qt 模型注册为 QObject 的属性 例如 我有AnimalModel http doc qt io qt 5 qtquick modelviewsdata cppmodels html qabstra
  • 如何在 Qt 中以编程方式制作一条水平线

    我想弄清楚如何在 Qt 中制作一条水平线 这很容易在设计器中创建 但我想以编程方式创建一个 我已经做了一些谷歌搜索并查看了 ui 文件中的 xml 但无法弄清楚任何内容 ui 文件中的 xml 如下所示

随机推荐

  • vue+element中如何设置单个el-date-picker开始时间和结束时间关联

    功能 选了开始时间 则结束时间只能选择开始时间之后的 选了结束时间 则开始时间只能选择结束时间之前的 重点是picker options属性 图示 代码展示 body 内部
  • JavaScript设计模式-02-单例模式

    Javascript 设计模式 02 单例模式 简介 单例就是保证一个类只有一个实例 实现的方法一般是先判断实例是否存在 如果存在直接返回 如果不存在就创建了再返回 确保了一个类只有一个实例对象 在JavaScript里 单例作为一个命名空
  • AIGC(AI Generated Content,人工智能生成内容)

    AIGC AI Generated Content 人工智能生成内容 什么是AIGC AIGC Artificial Intelligence Generated Content AI Generated Content 中文译为人工智能生
  • 读《effective modern c++》笔记总结

    文章目录 一 类型推导与auto 模板类型推导 ParamType是一个指针或引用 但不是通用引用 ParamType是一个通用引用 ParamType即不是指针也不是引用 数组实参 函数实参 auto类型推导 二 decltype的理解
  • make menuconfig报错:Build dependency: Please install Git (git-core) >= 1.6.5

    版本号为chaos calmer 15 05 1 注意 在执行make menuconfig的时候 会报一个错误 如下 Build dependency Please install Git git core gt 1 6 5 这是open
  • 节流与防抖

    1 我们先了解为什么要节流和防抖 我们给一个inpu输入框绑定一个oninput事件 此时我们输入 前端开发 四个字 我们 观察以下后台打印
  • 树莓派视觉小车 -- 小球追踪(颜色追踪)(OpenCV色彩空间HSV)

    目录 效果展示 基础理论 HSV 为什么用HSV空间而不是RGB空间 HSV 1 Hue 色相 2 Value 明度 3 Saturation 饱和度 一 初始化 滑动条初始化 1 创建回调函数 2 窗口设置 名称 3 滑动条设置 代码 二
  • Linux环境安装开发grafana插件(一)试水

    继续我们探索grafana结合Skywalking 为了更加灵活的应用图表 尝试开发grafana的panel插件 但试水并不顺利 所以把第一步目标缩小到安装一个自定义插件 参考了不少文章 终于成功 但各类参考要么比较碎片化 要么有些地方过
  • Typescript学习笔记

    Typescript学习笔记 什么是Typescript TypeScript是一种由微软开发的开源 跨平台的编程语言 它是JavaScript的超集 最终会被编译为JavaScript代码 TypeScript适合用来编写基于node的大
  • def __int__(self):的作用

    def int self 名称 初始化方法 构造方法 构造函数 作用 当我们创建好一个实例对象之后 会自动调用这个方法 来初始化这个对象 实例化后传入的参数会到此方法中来 构造方法 self name name此种语句将参数赋给实例 此类中
  • vue3+ts+echars实现中国为中心中文版世界地图(包含配置文件)

  • Python ERROR: Could not install packages due to an OSError:XXX解决方法

    Python ERROR Could not install packages due to an OSError XXX解决方法 文章目录 Python ERROR Could not install packages due to an
  • 滑动窗口专题(字节面试题)

    关键字 连续数组 字串 1 和为s的连续正整数序列 剑指offer57 II 输入一个正整数 target 输出所有和为 target 的连续正整数序列 至少含有两个数 序列内的数字由小到大排列 不同序列按照首个数字从小到大排列 示例 1
  • Linux下软件安装的命令

    源码安装 以源代码安装软件 每次都需要配置操作系统 配置编译参数 实际编译 最后还要依据个人喜好的方式来安装软件 这个过程很麻烦很累人 RPM安装软件的默认路径 注意 etc 配置文件放置目录 usr bin 一些可执行文件 usr lib
  • [计算机毕业设计]改进粒子群算法的监测资源调度

    前言 大四是整个大学期间最忙碌的时光 一边要忙着准备考研 考公 考教资或者实习为毕业后面临的就业升学做准备 一边要为毕业设计耗费大量精力 近几年各个学校要求的毕设项目越来越难 有不少课题是研究生级别难度的 对本科同学来说是充满挑战 为帮助大
  • 基于Hexo+Matery的LuckyBlog开源搭建教程

    前言 之前在B站上发布了个人博客的视频 播放量也破千了 有网友私聊也想要搭建一个这样的博客 经过一段时间的准备 现将本人博客的源代码公布出来 大家只需要根据以下的步骤 即可快速搭建一个漂亮完善的博客 0x01 LuckyBlog 介绍 上一
  • OJ编程之多组输入----牛客网----BC41 你是天才吗?

    OJ编程之多组输入 牛客网 BC41 你是天才吗 题目要求 错误代码 include
  • JavaScript 简介

    简介 JavaScript是一门脚本语言 这门语言主要用于 HTML 和 web 更可广泛用于服务器 PC 笔记本电脑 平板电脑和智能手机等设备 前端开发中JavaScript代码可以被插入到HTML页面代码中使用 并由浏览器来执行 示例
  • 关于打代码的一些些心得

    些许废话 零零散散也正式以打代码为生快一年半了 从代码写的稀碎到稍微能总结出一点东西 也算是一个一直在向上缓慢行走的状态了 很难说我喜欢代码这件事 原本选择也只是为了糊口 但从面向百度编程 到一点点写出带着自己风格的代码 再到可以略微静下来
  • Qt 实现压缩文件、文件夹和解压缩操作zip

    一 实现方式 通过Qt自带的库来实现 使用多线程方式 通过信号和槽来触发压缩与解压缩 并将压缩和解压缩结果回传过来 使用的类 include QtGui private qzipreader p h include QtGui privat