专业的编程技术博客社区

网站首页 > 博客文章 正文

Qt结合miniz压缩/解压zip文件(qt读取压缩文件)

baijin 2025-06-09 20:03:32 博客文章 1 ℃ 0 评论

Qt解压、压缩文件的方案有很多种,但是很多都环境搭建复杂,比如QuaZIP,环境搭建半天不成功。这里我用miniz这种最简单方式,我只是简单的解压、压缩一个zip文件而已。只需要包含miniz.c和miniz.h。这里我又封装了一下,亲测可用,代码如下,大家多多指教。

# MinizTest.pro
QT = core

CONFIG += c++17 cmdline

SOURCES += \
        main.cpp \
        miniz/MinizExtractor.cpp \
        miniz/miniz.c

HEADERS += \
        miniz/MinizExtractor.h \
        miniz/miniz.h

# 包含 miniz 头文件路径
INCLUDEPATH += miniz

# Default rules for deployment.
qnx: target.path = /tmp/${TARGET}/bin
else: unix:!android: target.path = /opt/${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
//  MinizExtractor.h
#ifndef MINIZEXTRACTOR_H
#define MINIZEXTRACTOR_H

#include <QString>

class MinizExtractor
{
public:
    // 解压 ZIP 文件到指定目录
    static bool extractZip(const QString &zipFilePath, const QString &targetDirectory);
    
    // 压缩文件或目录到 ZIP 文件
    static bool compressToZip(const QString &sourcePath, const QString &zipFilePath);

private:
    MinizExtractor() = delete; // 禁止实例化,仅使用静态方法
};

#endif // MINIZEXTRACTOR_H 
// MinizExtractor.cpp
#include "MinizExtractor.h"
#include "miniz.h"
#include <QDebug>
#include <QFileInfo>
#include <QDir>
#include <QDirIterator>

bool MinizExtractor::extractZip(const QString &zipFilePath, const QString &targetDirectory)
{
    // 检查输入参数
    if (zipFilePath.isEmpty() || targetDirectory.isEmpty()) {
        qDebug() << "Error: Input parameters cannot be empty";
        return false;
    }
    
    QFileInfo zipInfo(zipFilePath);
    if (!zipInfo.exists() || !zipInfo.isFile()) {
        qDebug() << "Error: ZIP file does not exist:" << zipFilePath;
        return false;
    }
    
    // 创建目标目录
    QDir targetDir(targetDirectory);
    if (!targetDir.exists()) {
        if (!targetDir.mkpath(".")) {
            qDebug() << "Error: Cannot create target directory:" << targetDirectory;
            return false;
        }
    }
    
    // 初始化 ZIP 读取器
    mz_zip_archive zip_archive;
    memset(&zip_archive, 0, sizeof(zip_archive));
    
    QByteArray zipPathBytes = zipFilePath.toLocal8Bit();
    if (!mz_zip_reader_init_file(&zip_archive, zipPathBytes.constData(), 0)) {
        qDebug() << "Error: Cannot open ZIP file:" << zipFilePath;
        return false;
    }
    
    // 获取 ZIP 文件中的文件总数
    mz_uint numFiles = mz_zip_reader_get_num_files(&zip_archive);
    
    bool success = true;
    
    // 遍历所有文件
    for (mz_uint i = 0; i < numFiles; i++) {
        mz_zip_archive_file_stat file_stat;
        if (!mz_zip_reader_file_stat(&zip_archive, i, &file_stat)) {
            qDebug() << "Error: Cannot get file info for entry" << i;
            success = false;
            break;
        }
        
        // 直接使用原始文件名,不做编码转换
        QString fileName = QString::fromLocal8Bit(file_stat.m_filename);
        
        // 清理路径
        fileName = fileName.replace('\\', '/');
        if (fileName.startsWith("./")) {
            fileName = fileName.mid(2);
        }
        if (fileName.startsWith('/')) {
            fileName = fileName.mid(1);
        }
        
        // 构建完整的输出路径
        QString outputPath = QDir(targetDirectory).absoluteFilePath(fileName);
        
        // 检查是否为目录
        if (mz_zip_reader_is_file_a_directory(&zip_archive, i) || fileName.endsWith('/')) {
            // 创建目录
            if (!QDir().mkpath(outputPath)) {
                qDebug() << "Error: Cannot create directory:" << outputPath;
                success = false;
                break;
            }
        } else {
            // 确保父目录存在
            QFileInfo fileInfo(outputPath);
            QDir parentDir = fileInfo.dir();
            if (!parentDir.exists()) {
                if (!parentDir.mkpath(".")) {
                    qDebug() << "Error: Cannot create directory structure for:" << outputPath;
                    success = false;
                    break;
                }
            }
            
            // 解压文件到磁盘
            QByteArray outputPathBytes = outputPath.toLocal8Bit();
            if (!mz_zip_reader_extract_to_file(&zip_archive, i, outputPathBytes.constData(), 0)) {
                qDebug() << "Error: Cannot extract file:" << fileName;
                success = false;
                break;
            }
        }
    }
    
    // 关闭 ZIP 文件
    mz_zip_reader_end(&zip_archive);
    
    return success;
}

bool MinizExtractor::compressToZip(const QString &sourcePath, const QString &zipFilePath)
{
    // 检查输入参数
    if (sourcePath.isEmpty() || zipFilePath.isEmpty()) {
        qDebug() << "Error: Input parameters cannot be empty";
        return false;
    }
    
    QFileInfo sourceInfo(sourcePath);
    if (!sourceInfo.exists()) {
        qDebug() << "Error: Source path does not exist:" << sourcePath;
        return false;
    }
    
    // 确保输出目录存在
    QFileInfo zipFileInfo(zipFilePath);
    QDir parentDir = zipFileInfo.dir();
    if (!parentDir.exists()) {
        if (!parentDir.mkpath(".")) {
            qDebug() << "Error: Cannot create output directory for ZIP file";
            return false;
        }
    }
    
    // 初始化 ZIP 写入器
    mz_zip_archive zip_archive;
    memset(&zip_archive, 0, sizeof(zip_archive));
    
    QByteArray zipPathBytes = zipFilePath.toLocal8Bit();
    if (!mz_zip_writer_init_file(&zip_archive, zipPathBytes.constData(), 0)) {
        qDebug() << "Error: Cannot create ZIP file:" << zipFilePath;
        return false;
    }
    
    bool success = true;
    
    if (sourceInfo.isFile()) {
        // 处理单个文件
        QString fileName = sourceInfo.fileName();
        QByteArray filePathBytes = sourcePath.toLocal8Bit();
        QByteArray fileNameBytes = fileName.toLocal8Bit();
        
        if (!mz_zip_writer_add_file(&zip_archive, fileNameBytes.constData(), filePathBytes.constData(), NULL, 0, MZ_BEST_COMPRESSION)) {
            qDebug() << "Error: Cannot add file to ZIP:" << fileName;
            success = false;
        }
    } else if (sourceInfo.isDir()) {
        // 处理目录
        QDir sourceDir(sourcePath);
        
        // 递归遍历源目录
        QDirIterator iterator(sourcePath, QDir::AllEntries | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
        
        while (iterator.hasNext()) {
            QString filePath = iterator.next();
            QFileInfo fileInfo(filePath);
            
            // 计算相对路径
            QString relativePath = sourceDir.relativeFilePath(filePath);
            relativePath = relativePath.replace('\\', '/'); // 统一使用正斜杠
            
            if (fileInfo.isDir()) {
                // 添加目录条目 (以 '/' 结尾)
                if (!relativePath.endsWith('/')) {
                    relativePath += '/';
                }
                
                QByteArray relativePathBytes = relativePath.toLocal8Bit();
                if (!mz_zip_writer_add_mem(&zip_archive, relativePathBytes.constData(), NULL, 0, MZ_NO_COMPRESSION)) {
                    qDebug() << "Error: Cannot add directory to ZIP:" << relativePath;
                    success = false;
                    break;
                }
            } else if (fileInfo.isFile()) {
                // 添加文件
                QByteArray filePathBytes = filePath.toLocal8Bit();
                QByteArray relativePathBytes = relativePath.toLocal8Bit();
                
                if (!mz_zip_writer_add_file(&zip_archive, relativePathBytes.constData(), filePathBytes.constData(), NULL, 0, MZ_BEST_COMPRESSION)) {
                    qDebug() << "Error: Cannot add file to ZIP:" << relativePath;
                    success = false;
                    break;
                }
            }
        }
    } else {
        qDebug() << "Error: Source path is neither a file nor a directory:" << sourcePath;
        success = false;
    }
    
    // 完成并关闭 ZIP 文件
    if (success) {
        if (!mz_zip_writer_finalize_archive(&zip_archive)) {
            qDebug() << "Error: Cannot finalize ZIP archive";
            success = false;
        }
    }
    
    mz_zip_writer_end(&zip_archive);
    
    return success;
}
// main.cpp
#include <QCoreApplication>
#include <QDebug>
#include "miniz/MinizExtractor.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 解压示例
    bool result = MinizExtractor::extractZip("./a.zip", "./a");
    
    if (result) {
        qDebug() << "Extraction completed successfully!";
    } else {
        qDebug() << "Extraction failed!";
        return -1;
    }

    // 压缩示例
    bool result2 = MinizExtractor:: compressToZip("./a.exe", "./a.zip");
    if (result2) {
        qDebug() << "Compression completed successfully!";
    } else {
        qDebug() << "Compression failed!";
        return -1;
    }
    
    return 0;
}

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表