当前位置: 首页 > article >正文

Qt C++ 使用 LZ4 库压缩成 zip格式;使用 QuaZip 打包

Summery:

Qt C++ 使用 LZ4 库压缩成 zip格式;使用 QuaZip 打包,这样,可以保证压缩速度,也可以保证,打成 zip 包;

LZ4 是一个专注于快速压缩和解压缩的库,但它本身并不直接支持生成 ZIP 格式的文件。ZIP 文件格式是一种容器格式,它不仅包含压缩数据,还包含文件元数据(如文件名、时间戳等)。如果希望生成标准的 ZIP 文件,可以使用 QuaZip(基于 zlib)来创建 ZIP 文件,同时结合 LZ4 进行高效压缩。

以下是实现步骤和示例代码:


实现步骤

  1. 使用 LZ4 压缩文件数据:

    • 对每个文件的数据使用 LZ4 进行压缩。

  2. 使用 QuaZip 创建 ZIP 文件:

    • 将压缩后的数据按 ZIP 文件格式写入,同时保留文件名和其他元数据。

  3. 保存 ZIP 文件到硬盘:

    • 使用 QFile 将生成的 ZIP 文件保存到硬盘。


开发环境配置

  1. LZ4 库:

    • 下载并编译 LZ4 库,将其集成到 Qt 项目中(参考前面的配置步骤)。

  2. 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 压缩的数据,可以使用以下步骤:

  1. 使用 QuaZip 解压 ZIP 文件。

  2. 使用 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 并不是适合所有文件压缩,有时压缩比很小;速度是快;适用场景有限;


http://www.kler.cn/a/591610.html

相关文章:

  • IT6636: 3-IN 1-OUT HDMI 2.1 (48 Gbps) Retiming Switch with Embedded MCU
  • 将 YOLO 格式的标注文件(.txt)转换为 VOC 格式的 XML 标注文件
  • 前后端图像分类系统搭建文档
  • docker 安装mysql
  • win10搭建opengl环境搭建并测试--输出立方体球体和碗型并在球体上贴图
  • 前端项目打包构建优化
  • vue3+antd+a-menu配置
  • 防止用户调试网页的若干方法
  • 数据结构 -- 树和二叉树
  • 从盒马看新零售:战略调整背后的零售行业风向-亿发
  • kafka指北
  • 快速进行数据验证的优雅实现-注解
  • 从PLC到云端:5G嵌入式网关的MQTT协议转换与Ubuntu二次开发全解析
  • VLLM:虚拟大型语言模型(Virtual Large Language Model)
  • AI Agent如何通过自然语言处理提升交互体验
  • 【图像处理】ISP(Image Signal Processor) 图像处理器的用途和工作原理?
  • 机器学习 [白板推导](二)[线性回归]
  • 【Go】运算符笔记
  • 安装并使用anaconda(宏观版)
  • HTML,CSS,JavaScript