我想知道Qt中是否有任何类可以压缩文件夹或文件。我使用 QProcess 进行压缩,它被压缩了,但我无法使用普通的压缩工具解压缩它。谁能告诉我如何使用 Qt api 类压缩文件夹/文件?
几年前我遇到过这样的问题,这是我的解决方案:
1)。获取 QuaZip(这是链接文本)
2)。将 quazip 源代码包含到您的项目文件中
标题:
HEADERS += src/quazip/crypt.h \
src/quazip/ioapi.h \
src/quazip/quazip.h \
src/quazip/quazipfile.h \
src/quazip/quazipfileinfo.h \
src/quazip/quazipnewinfo.h \
src/quazip/unzip.h \
src/quazip/zip.h \
...
来源:
SOURCES += src/quazip/ioapi.c \
src/quazip/quazip.cpp \
src/quazip/quazipfile.cpp \
src/quazip/quazipnewinfo.cpp \
src/quazip/unzip.c \
src/quazip/zip.c
...
3)。添加标题
#include "quazip/quazip.h"
#include "quazip/quazipfile.h"
4)。使用提取功能:
static bool extract(const QString & filePath, const QString & extDirPath, const QString & singleFileName = QString("")) {
QuaZip zip(filePath);
if (!zip.open(QuaZip::mdUnzip)) {
qWarning("testRead(): zip.open(): %d", zip.getZipError());
return false;
}
zip.setFileNameCodec("IBM866");
qWarning("%d entries\n", zip.getEntriesCount());
qWarning("Global comment: %s\n", zip.getComment().toLocal8Bit().constData());
QuaZipFileInfo info;
QuaZipFile file(&zip);
QFile out;
QString name;
char c;
for (bool more = zip.goToFirstFile(); more; more = zip.goToNextFile()) {
if (!zip.getCurrentFileInfo(&info)) {
qWarning("testRead(): getCurrentFileInfo(): %d\n", zip.getZipError());
return false;
}
if (!singleFileName.isEmpty())
if (!info.name.contains(singleFileName))
continue;
if (!file.open(QIODevice::ReadOnly)) {
qWarning("testRead(): file.open(): %d", file.getZipError());
return false;
}
name = QString("%1/%2").arg(extDirPath).arg(file.getActualFileName());
if (file.getZipError() != UNZ_OK) {
qWarning("testRead(): file.getFileName(): %d", file.getZipError());
return false;
}
//out.setFileName("out/" + name);
out.setFileName(name);
// this will fail if "name" contains subdirectories, but we don't mind that
out.open(QIODevice::WriteOnly);
// Slow like hell (on GNU/Linux at least), but it is not my fault.
// Not ZIP/UNZIP package's fault either.
// The slowest thing here is out.putChar(c).
while (file.getChar(&c)) out.putChar(c);
out.close();
if (file.getZipError() != UNZ_OK) {
qWarning("testRead(): file.getFileName(): %d", file.getZipError());
return false;
}
if (!file.atEnd()) {
qWarning("testRead(): read all but not EOF");
return false;
}
file.close();
if (file.getZipError() != UNZ_OK) {
qWarning("testRead(): file.close(): %d", file.getZipError());
return false;
}
}
zip.close();
if (zip.getZipError() != UNZ_OK) {
qWarning("testRead(): zip.close(): %d", zip.getZipError());
return false;
}
return true;
}
及存档功能:
static bool archive(const QString & filePath, const QDir & dir, const QString & comment = QString("")) {
QuaZip zip(filePath);
zip.setFileNameCodec("IBM866");
if (!zip.open(QuaZip::mdCreate)) {
myMessageOutput(true, QtDebugMsg, QString("testCreate(): zip.open(): %1").arg(zip.getZipError()));
return false;
}
if (!dir.exists()) {
myMessageOutput(true, QtDebugMsg, QString("dir.exists(%1)=FALSE").arg(dir.absolutePath()));
return false;
}
QFile inFile;
// Получаем список файлов и папок рекурсивно
QStringList sl;
recurseAddDir(dir, sl);
// Создаем массив состоящий из QFileInfo объектов
QFileInfoList files;
foreach (QString fn, sl) files << QFileInfo(fn);
QuaZipFile outFile(&zip);
char c;
foreach(QFileInfo fileInfo, files) {
if (!fileInfo.isFile())
continue;
// Если файл в поддиректории, то добавляем имя этой поддиректории к именам файлов
// например: fileInfo.filePath() = "D:\Work\Sources\SAGO\svn\sago\Release\tmp_DOCSWIN\Folder\123.opn"
// тогда после удаления части строки fileNameWithSubFolders будет равен "Folder\123.opn" и т.д.
QString fileNameWithRelativePath = fileInfo.filePath().remove(0, dir.absolutePath().length() + 1);
inFile.setFileName(fileInfo.filePath());
if (!inFile.open(QIODevice::ReadOnly)) {
myMessageOutput(true, QtDebugMsg, QString("testCreate(): inFile.open(): %1").arg(inFile.errorString().toLocal8Bit().constData()));
return false;
}
if (!outFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileNameWithRelativePath, fileInfo.filePath()))) {
myMessageOutput(true, QtDebugMsg, QString("testCreate(): outFile.open(): %1").arg(outFile.getZipError()));
return false;
}
while (inFile.getChar(&c) && outFile.putChar(c));
if (outFile.getZipError() != UNZ_OK) {
myMessageOutput(true, QtDebugMsg, QString("testCreate(): outFile.putChar(): %1").arg(outFile.getZipError()));
return false;
}
outFile.close();
if (outFile.getZipError() != UNZ_OK) {
myMessageOutput(true, QtDebugMsg, QString("testCreate(): outFile.close(): %1").arg(outFile.getZipError()));
return false;
}
inFile.close();
}
// + комментарий
if (!comment.isEmpty())
zip.setComment(comment);
zip.close();
if (zip.getZipError() != 0) {
myMessageOutput(true, QtDebugMsg, QString("testCreate(): zip.close(): %1").arg(zip.getZipError()));
return false;
}
return true;
}
5)。享受;)
更新:适用于CapDroid。
/* Рекурсивно ищет все файлы в директории \a и добавляет в список \b */
static void recurseAddDir(QDir d, QStringList & list) {
QStringList qsl = d.entryList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files);
foreach (QString file, qsl) {
QFileInfo finfo(QString("%1/%2").arg(d.path()).arg(file));
if (finfo.isSymLink())
return;
if (finfo.isDir()) {
QString dirname = finfo.fileName();
QDir sd(finfo.filePath());
recurseAddDir(sd, list);
} else
list << QDir::toNativeSeparators(finfo.filePath());
}
}
我使用的是Qt 5.12版本。
在 pro 文件中添加“QT += gui-private”。
在cpp文件中,示例:
#include "QtGui/private/qzipreader_p.h"
#include "QtGui/private/qzipwriter_p.h"
......
QFileInfoList list = getFileList(zipPath);//zipPath
QZipWriter writer(zipFile);
if(list.size()<=0){
qDebug()<<"there is no file to zip, please check it";
return false;
}
//
for(int i=0;i != list.size(); i++){
QString filename=list.at(i).filePath();
qDebug()<<"filename:"<<filename.mid(pos+1);
QFile file(filename);
if(file.exists()){
file.open(QIODevice::ReadOnly);
writer.addFile(filename.mid(pos+1), file.readAll());
file.close();
}
else{
qDebug()<<"file not exist:"<<filename;
}
}
writer.close();
我认为你做不到。据我所知,qcompress 和 quncompress 仅提供流的压缩等。这意味着它们不会创建真正的 zip 文件所需的标头(也说明文件中包含哪些文件)。
然而,有一个名为 QuaZip 的开源 Qt 库,它使用 zlib(随 qt 一起提供)并提供该功能。
https://libzip.org/license/ 拥有 BSD 许可证,您可以在任何地方使用它
示例(在 Linux 上) 在
.pro
文件中:
HEADERS += /usr/include/zip.h
LIBS += -L/usr/lib/x86_64-linux-gnu/ -lzip
INCLUDEPATH += /usr/lib/x86_64-linux-gnu/libzip/include headers
压缩文件的功能:
int PutFileIntoZip(const QString &filePath)
{
QFile regFile(filePath);
Q_ASSERT(regFile.exists());
const bool canOpenRegFile=regFile.open(QIODevice::ReadOnly);
if(canOpenRegFile)
{
QString fileNameExpansion=filePath.section(QDir::separator(),-1,-1);
const QStringRef fileName(&fileNameExpansion, 0, fileNameExpansion.length()-4);//22222.bin -> 22222
int errorFlagCreateZip = 0;
const QString zipPath=QDir::homePath()+QDir::separator()+fileName + ".zip";
zip*const zipHandle = zip_open(zipPath.toLatin1().constData(), ZIP_CREATE, &errorFlagCreateZip);
if (ZIP_ER_OK==errorFlagCreateZip)
{
FILE* const fileC = fdopen(regFile.handle(), "r");
zip_source* const source = zip_source_filep(zipHandle, fileC, 0, regFile.size());
if (source!=nullptr)
{
const zip_int64_t result = zip_file_add(zipHandle, fileNameExpansion.toLatin1().constData(), source, ZIP_FL_OVERWRITE);
if (result>=0)
{
zip_set_file_compression(zipHandle, result, ZIP_CM_DEFLATE64, 0);
qDebug()<< "Done";
}
else
{
zip_source_free(source);
}
}
int result = zip_close(zipHandle);
fclose(fileC);
regFile.close();
return result;
}
else
{
zip_error_t error;
zip_error_init_with_code(&error, errorFlagCreateZip);
const int zipCreationErrorCode = zip_error_code_zip(&error);
regFile.close();
return zipCreationErrorCode;
}
}
else
{
qDebug()<< regFile.errorString();
return -1;
}
}
使用QMicroz
要压缩文件夹:
QMicroz::compress_folder("source_path", "zip_file_path");
要压缩文件/文件夹列表:
QMicroz::compress_({"file_path", "folder_path", "file2_path"});