设计网站国外网站,企业微信app下载安装官方最新版,敦煌网跨境电商怎么样,网站图片地址怎么做的前面讲了很多Qt的文件操作#xff0c;文件操作自然就包括压缩与解压缩文件了#xff0c;正好最近项目里要用到压缩以及解压缩文件#xff0c;所以就研究了一下Qt如何压缩与解压缩文件。
QZipReader/QZipWriter
QZipReader 和 QZipWriter 类提供了用于读取和写入 ZIP 格式文…前面讲了很多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(-mx3);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 的详细介绍 功能 zlib 库提供了数据压缩和解压缩的功能支持使用 DEFLATE 算法进行数据压缩。zlib 提供了简单的 API易于集成到各种应用程序中。zlib 还支持在压缩数据中添加校验和以确保数据的完整性。 特点 高效性zlib 使用 DEFLATE 算法进行数据压缩具有较高的压缩比和压缩速度。跨平台性zlib 可以在各种操作系统上运行包括 Windows、Linux、macOS 等。开源性zlib 是一个开源库使用 zlib 的应用程序可以遵循 zlib 的开源许可协议。 使用场景 zlib 可用于在应用程序中对数据进行压缩减小数据传输和存储的大小。zlib 还可用于处理压缩文件格式如 ZIP、PNG、HTTP 的 gzip 压缩等。zlib 也常用于实时数据流的压缩如网络传输中的数据压缩。 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_castBytef *(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_castBytef *(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的前提是已经编译好了zlibzlib的编译前面已经讲了。这里直接开始讲QuaZIP的编译与使用。
首先下载QuaZIPQuaZIP官网。下载之后进行解压 可以看到里面有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 QMainWindowQT_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 QFileDialogMainWindow::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的库文件也在里面建议自己编译因为平台或者编译软件可能与我不同我的环境是WindowsVS2022Qt5.15.2。
其他相关压缩以及解压缩这里就不做介绍了有兴趣的可以下去自己研究一下。