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); // 假设原始文件大小为 1024qDebug() << "File:" << zipFile.getActualFileName();qDebug() << "Decompressed content:" << decompressedData;}zip.close();
}// 示例:解压 ZIP 文件
unpackZipFile("compressed_files.zip");
总结
-
通过将 LZ4 压缩后的数据存储为 ZIP 文件中的未压缩条目,可以充分发挥 LZ4 的速度优势。
-
生成的 ZIP 文件是标准的 ZIP 格式,兼容常见的解压工具。
-
这种方法在速度和兼容性之间取得了良好的平衡。
注意: lz4 并不是适合所有文件压缩,有时压缩比很小;速度是快;适用场景有限;