Qt C++ 使用 LZ4 库压缩成 zip格式;使用 QuaZip 打包
Summery:
Qt C++ 使用 LZ4 库压缩成 zip格式;使用 QuaZip 打包,这样,可以保证压缩速度,也可以保证,打成 zip 包;
LZ4 是一个专注于快速压缩和解压缩的库,但它本身并不直接支持生成 ZIP 格式的文件。ZIP 文件格式是一种容器格式,它不仅包含压缩数据,还包含文件元数据(如文件名、时间戳等)。如果希望生成标准的 ZIP 文件,可以使用 QuaZip(基于 zlib)来创建 ZIP 文件,同时结合 LZ4 进行高效压缩。
以下是实现步骤和示例代码:
实现步骤
-
使用 LZ4 压缩文件数据:
-
对每个文件的数据使用 LZ4 进行压缩。
-
-
使用 QuaZip 创建 ZIP 文件:
-
将压缩后的数据按 ZIP 文件格式写入,同时保留文件名和其他元数据。
-
-
保存 ZIP 文件到硬盘:
-
使用
QFile
将生成的 ZIP 文件保存到硬盘。
-
开发环境配置
-
LZ4 库:
-
下载并编译 LZ4 库,将其集成到 Qt 项目中(参考前面的配置步骤)。
-
-
QuaZip 库:
-
下载 QuaZip 库并集成到 Qt 项目中。
-
QuaZip 的 GitHub 地址:QuaZip GitHub
-
示例代码
以下是一个完整的示例,展示如何将多个文件的数据从共享内存中读取,使用 LZ4 压缩,然后打包成 ZIP 文件并保存到硬盘:
#include <QCoreApplication>
#include <QSharedMemory>
#include <QFile>
#include <QDebug>
#include <quazip/quazip.h>
#include <quazip/quazipfile.h>
#include "lz4.h"
// 使用 LZ4 压缩数据
QByteArray compressData(const QByteArray &data) {
int maxCompressedSize = LZ4_compressBound(data.size());
QByteArray compressedData(maxCompressedSize, 0);
int compressedSize = LZ4_compress_default(data.data(), compressedData.data(), data.size(), maxCompressedSize);
if (compressedSize <= 0) {
qWarning() << "Compression failed!";
return QByteArray();
}
compressedData.resize(compressedSize);
return compressedData;
}
// 将多个文件打包成 ZIP 文件(使用 LZ4 压缩)
bool packFilesToZip(const QString &zipFilePath, const QList<QPair<QString, QByteArray>> &files) {
// 创建 QuaZip 对象
QuaZip zip(zipFilePath);
if (!zip.open(QuaZip::mdCreate)) {
qWarning() << "Failed to create zip file:" << zipFilePath;
return false;
}
// 逐个添加文件
for (const auto &file : files) {
const QString &fileName = file.first;
const QByteArray &fileData = file.second;
// 创建 ZIP 文件中的条目
QuaZipFile zipFile(&zip);
QuaZipNewInfo newInfo(fileName);
// 打开文件并设置压缩方法为 STORED(未压缩)
if (!zipFile.open(QIODevice::WriteOnly, newInfo, nullptr, false, Z_NO_COMPRESSION)) {
qWarning() << "Failed to add file to zip:" << fileName;
zip.close();
return false;
}
// 将文件数据写入 ZIP 文件
zipFile.write(fileData);
// 关闭文件
zipFile.close();
}
// 关闭 ZIP 文件
zip.close();
return true;
}
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
// 示例:创建共享内存并写入数据
QSharedMemory sharedMemory1("shared_memory_1");
sharedMemory1.create(1024); // 创建 1KB 共享内存
sharedMemory1.lock();
memcpy(sharedMemory1.data(), "This is the content of file1.", 28); // 写入数据
sharedMemory1.unlock();
QSharedMemory sharedMemory2("shared_memory_2");
sharedMemory2.create(1024); // 创建 1KB 共享内存
sharedMemory2.lock();
memcpy(sharedMemory2.data(), "This is the content of file2.", 28); // 写入数据
sharedMemory2.unlock();
// 从共享内存读取数据
sharedMemory1.lock();
QByteArray file1Data(static_cast<const char*>(sharedMemory1.constData()), sharedMemory1.size());
sharedMemory1.unlock();
sharedMemory2.lock();
QByteArray file2Data(static_cast<const char*>(sharedMemory2.constData()), sharedMemory2.size());
sharedMemory2.unlock();
// 使用 LZ4 压缩文件数据
QByteArray compressedFile1Data = compressData(file1Data);
QByteArray compressedFile2Data = compressData(file2Data);
if (compressedFile1Data.isEmpty() || compressedFile2Data.isEmpty()) {
qWarning() << "Failed to compress file data!";
return -1;
}
// 示例文件列表(文件名 + 压缩后的数据)
QList<QPair<QString, QByteArray>> files = {
{"file1.txt.lz4", compressedFile1Data},
{"file2.txt.lz4", compressedFile2Data}
};
// 将文件打包成 ZIP 文件并保存到硬盘
QString outputFilePath = "compressed_files.zip";
if (packFilesToZip(outputFilePath, files)) {
qDebug() << "Files successfully compressed and saved to:" << outputFilePath;
} else {
qDebug() << "Failed to compress and save files.";
}
return a.exec();
}
解压缩 ZIP 文件
如果需要解压缩 ZIP 文件并提取 LZ4 压缩的数据,可以使用以下步骤:
-
使用 QuaZip 解压 ZIP 文件。
-
使用 LZ4 解压缩提取的文件数据。
解压缩示例代码
#include <quazip/quazip.h>
#include <quazip/quazipfile.h>
#include "lz4.h"
// 解压缩 LZ4 数据
QByteArray decompressData(const QByteArray &compressedData, int originalSize) {
QByteArray decompressedData(originalSize, 0);
int decompressedSize = LZ4_decompress_safe(compressedData.data(), decompressedData.data(), compressedData.size(), originalSize);
if (decompressedSize <= 0) {
qWarning() << "Decompression failed!";
return QByteArray();
}
decompressedData.resize(decompressedSize);
return decompressedData;
}
// 解压 ZIP 文件并解压缩 LZ4 数据
void unpackZipFile(const QString &zipFilePath) {
QuaZip zip(zipFilePath);
if (!zip.open(QuaZip::mdUnzip)) {
qWarning() << "Failed to open zip file:" << zipFilePath;
return;
}
for (bool more = zip.goToFirstFile(); more; more = zip.goToNextFile()) {
QuaZipFile zipFile(&zip);
if (!zipFile.open(QIODevice::ReadOnly)) {
qWarning() << "Failed to open file in zip:" << zipFile.getActualFileName();
continue;
}
// 读取压缩后的数据
QByteArray compressedData = zipFile.readAll();
zipFile.close();
// 解压缩数据
QByteArray decompressedData = decompressData(compressedData, 1024); // 假设原始文件大小为 1024
qDebug() << "File:" << zipFile.getActualFileName();
qDebug() << "Decompressed content:" << decompressedData;
}
zip.close();
}
// 示例:解压 ZIP 文件
unpackZipFile("compressed_files.zip");
总结
-
通过将 LZ4 压缩后的数据存储为 ZIP 文件中的未压缩条目,可以充分发挥 LZ4 的速度优势。
-
生成的 ZIP 文件是标准的 ZIP 格式,兼容常见的解压工具。
-
这种方法在速度和兼容性之间取得了良好的平衡。
注意: lz4 并不是适合所有文件压缩,有时压缩比很小;速度是快;适用场景有限;