天天看點

使用Zlib對檔案和目錄進加密打包和解包

   zlib就不做解釋了,本人使用的是1.2.7版本,并用C++進行了封裝,用到了Qt。

功能:

1.使用線程,不會卡死界面支.

2.支援遞歸目錄,目錄和單個檔案。

3.可以同時進行多項任務。

4.傳回每項任務的任務進度。

5.打包和解包的詳細過程資訊。

6.支援從封包件中隻解壓一個檔案。

步驟:

1.下載下傳zlib壓縮包并解壓。

2.找到zlib解壓目錄下的zlib-1.2.7\contrib\masmx64目錄,這裡是64位的,32位的目錄為zlib-1.2.7\contrib\masmx86。

3.啟動vs指令行工具如(VS2013 x64 本機工具指令提示) , 切換到步驟2的目錄。

4.将bld_ml64.bat拖到步驟3的指令行工具并執行。

5.執行步驟4後在zlib-1.2.7\contrib目錄下找到vstudio目錄,然後找到vc10目錄下的vs工程檔案打開編譯生成zlib庫。

工程配置就不在啰嗦了, 類SCPackageMgr對每個打包或者解包任務進行管理,SCPackageWorker是實際工作的類,由于打包可能檔案很多很大,為了防止界面卡死,是以SCPackageWorker實際是個線程。這裡簡單的對每一個任務建立了一個線程,其實可以對任務進行分組,每個線程負責一組任務,這就留給讀者自己實作了。

頭檔案:

Copyright:北京四維(數創)科技有限公司
Author:
Date:2017-08-25
Description:對檔案或者目錄進行加密打包和解包
**************************************************/
#ifndef SCPACKAGEMGR_H
#define SCPACKAGEMGR_H
#include <QObject>
#include <QVector>
#include <QThread>
#ifdef _WIN64
#define ZLIB_WINAPI
#endif
#include "unzip.h"
#include "zip.h"
class SCPackageWorker;
class QThread;
typedef QVector<QString> FileList;
typedef QVector<QString> DirList;
typedef QVector<SCPackageWorker *> TaskList;
class SCPackageMgr: public QObject
{
    Q_OBJECT
public:
    static SCPackageMgr&instance();
    /*************************************************
    Function:       addDir
    Description:    添加要打包的目錄
    Input:          dir,需要打包的目錄
    Output:         無
    Return:         void
    *************************************************/
    void addDir(const QString &dir);
    /*************************************************
    Function:       addFile
    Description:    添加要打包的檔案
    Input:          path,需要打包的檔案完整路徑
    Output:         無
    Return:         void
    *************************************************/
    void addFile(const QString &path);
    /*************************************************
    Function:        package
    Description:     開始打包, 打包addDir和addFile添加的檔案和檔案夾
    Input:           packagePath,打包後的檔案完整路徑如F:\1.zip
    Input:           passWord,對打封包件進行加密的密碼
    Input:           level,壓縮級别(0-9), 預設為9
    Output:          無
    Return:         void
    *************************************************/
    void package(const QString &packagePath, const QString &passWord = "", int level = 9);
    /*************************************************
    Function:        unPackage
    Description:     解包一個壓縮包
    Input:           strPackageFilePath,需要解包的檔案路徑
    Input:           strUnPackageDir,解壓目錄
    Input:           password,密碼對應package打包的密碼
    Output:          無
    Return:         void
    *************************************************/
    void unPackage(const QString &strPackageFilePath, const QString &strUnPackageDir, const QString &password="");
    /*************************************************
    Function:        unPackFileFromPackge
    Description:     解包壓縮包中特定的一個檔案
    Input:           strPackageFilePath,需要解包的檔案路徑
    Input:           strUnPackageDir,解壓目錄
    Input:           password,密碼對應package打包的密碼
    Input:           fileNameInPackage,該檔案在包中的名稱
    Output:          無
    Return:         void
    *************************************************/
    void unPackFileFromPackge(const QString &strPackageFilePath,
                              const QString &strUnPackageDir,
                              const QString &fileNameInPackage,
                              const QString &password = "");
    /*************************************************
    Function:        clear
    Description:     清空目前需要打包的内容,為下一次打包做準備, 每次新添加目錄或者檔案調用
    Input:           無
    Output:          無
    Return:         void
    *************************************************/
     void clear();
private:
    SCPackageMgr();
    SCPackageMgr(const SCPackageMgr&){}
    ~SCPackageMgr();
    SCPackageMgr &operator =(const SCPackageMgr &){}
signals:
    /*************************************************
    Function:        packageProgress
    Description:     通知打包的進度
    Output:          filePath,打包的目錄對應package參數1傳入的檔案路徑
    Output:          progress,進度。
    Return:         void
    *************************************************/
    void packageProgress(const QString &filePath, const QString& progress);
    /*************************************************
    Function:        unPackageProgress
    Description:     通知解包的進度
    Output:          filePath,解包的目錄對應unPackage參數1傳入的檔案路徑
    Output:          progress,進度。
    Return:         void
    *************************************************/
    void unPackageProgress(const QString &filePath, const QString& progress);
    /*************************************************
    Function:        progressInfo
    Description:     解包或者打包的詳細資訊,如目前正在對某個檔案壓縮
    Output:          info,資訊
    Return:         void
    *************************************************/
    void progressInfo(const QString &info);
private:
    //任務清單
    TaskList m_tasks;
    //需要打包的檔案清單
    FileList m_files;
    //需要打包的目錄清單
    DirList m_dirs;
};
class SCPackageWorker : public QThread
{
    Q_OBJECT
    enum WorkerType
    {
        PACKAGE_TYPE = 1,
        UNPACKAGE_TYPE,
        UNPACKAGE_ONE_TYPE
    };
private:
    /*************************************************
    Function:        package
    Description:     開始打包, 打包addDir和addFile添加的檔案和檔案夾
    Input:           packagePath,打包後的檔案完整路徑如F:\1.zip
    Input:           passWord,對打封包件進行加密的密碼
    Input:           level,壓縮級别(0-9), 預設為9
    Output:          無
    Return:         void
    *************************************************/
    void package(const QString &packagePath, const QString &passWord, int level = 9);
    /*************************************************
    Function:        unPackage
    Description:     解包一個壓縮包
    Input:           strPackageFilePath,需要解包的檔案路徑
    Input:           strUnPackageDir,解壓目錄
    Input:           password,密碼對應package打包的密碼
    Output:          無
    Return:         void
    *************************************************/
    void unPackage(const QString &strPackageFilePath, const QString &strUnPackageDir, const QString &password);
    /*************************************************
    Function:        unPackFileFromPackge
    Description:     解包壓縮包中特定的一個檔案
    Input:           strPackageFilePath,需要解包的檔案路徑
    Input:           strUnPackageDir,解壓目錄
    Input:           password,密碼對應package打包的密碼
    Input:           fileNameInPackage,該檔案在包中的名稱
    Output:          無
    Return:         void
    *************************************************/
    void unPackFileFromPackge(const QString &strPackageFilePath,
                              const QString &strUnPackageDir,
                              const QString &fileNameInPackage,
                              const QString &password);
private:
    void run();
    SCPackageWorker(){}
    SCPackageWorker(const FileList &fileList, const DirList &dirList);
    SCPackageWorker(const SCPackageWorker&){}
    ~SCPackageWorker(){}
    SCPackageWorker &operator =(const SCPackageWorker &){}
    /*************************************************
    Function:        packageByDir
    Description:     對指定目錄進行遞歸打包
    Input:           strPath,需要打包的目錄
    Input:           parentDir,父目錄
    Input:           password,密碼
    Input:           level,壓縮級别
    Output:          無
    Return:         void
    *************************************************/
    void packageByDir(zipFile zf, const QString& strPath, const QString& parentDir, const QString &passWord, int level);
    /*************************************************
    Function:        packageByFile
    Description:     對指定檔案行打包
    Input:           fileNameInPackage,指定打包的檔案在封包件的名稱
    Input:           filePath,需要打封包件的完整路徑
    Input:           password,密碼
    Input:           level,壓縮級别
    Output:          無
    Return:         void
    *************************************************/
    void packageByFile(zipFile zf,  const QString &fileNameInPackage, const QString &filePath, const QString &passWord, int level);
    /*************************************************
    Function:        getDirFileCount
    Description:     擷取目錄下的檔案個數
    Input:           dir,需要計算的目錄
    Input:           count,檔案個數
    Output:          無
    Return:         void
    *************************************************/
    void getDirFileCount(const QString &dir, int &count);
    /*************************************************
    Function:        startPackage
    Description:     開始打包
    Input:           無
    Output:          無
    Return:         void
    *************************************************/
    void startPackage();
    /*************************************************
    Function:        startUnPackage
    Description:     開始解包
    Input:           無
    Output:          無
    Return:         void
    *************************************************/
    void startUnPackage();
    /*************************************************
    Function:        startUnPacgeOne
    Description:     解包一個
    Input:           無
    Output:          無
    Return:         void
    *************************************************/
    void startUnPacgeOne();
signals:
    /*************************************************
    Function:        packageProgress
    Description:     通知打包的進度
    Output:          filePath,打包的目錄對應package參數1傳入的檔案路徑
    Output:          progress,進度。
    Return:         void
    *************************************************/
    void packageProgress(const QString &filePath, const QString& progress);
    /*************************************************
    Function:        unPackageProgress
    Description:     通知解包的進度
    Output:          filePath,解包的目錄對應unPackage參數1傳入的檔案路徑
    Output:          progress,進度。
    Return:         void
    *************************************************/
    void unPackageProgress(const QString &filePath, const QString& progress);
    /*************************************************
    Function:        progressInfo
    Description:     解包或者打包的詳細資訊,如目前正在對某個檔案壓縮
    Output:          info,資訊
    Return:         void
    *************************************************/
    void progressInfo(const QString &info);
private:
    //需要打包的檔案清單
    FileList m_files;
    //需要打包的目錄清單
    DirList m_dirs;
    //打包或者解包的檔案路徑,用于進度信号發出
    QString m_strPackageFilePath;
    QString m_strUnPackageFilePath;
    QString m_strUnPackageDir;
    QString m_strPw;
    int m_nlevel;
    //要解壓的單個檔案名
    QString m_strUnPackageOneFileName;
    //上一次進度
    QString m_strLastProgress;
    //打封包件總個數
    int m_nTasks;
    //打包一個檔案所占%
    double m_nProgerss;
    //打包次數
    int m_nLoopCount;
    //解壓打包
    WorkerType m_WorkerType;
    friend class SCPackageMgr;
};

#endif // SCPACKAGEMGR_H



           

/*************************************************

#include "SCPackageMgr.h"
#include <qt_windows.h>
#include <QDebug>
#include <QDir>
#include <QThread>
#include <iostream>
#include <fstream>
using namespace std;
#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
#define WRITEBUFFERSIZE (8192)
void SCPackageMgr::clear()
{
    m_dirs.clear();
    m_files.clear();
}
SCPackageMgr &SCPackageMgr::instance()
{
    static SCPackageMgr mgr;
    return mgr;
}
void SCPackageMgr::addDir(const QString &dir)
{
    m_dirs.push_back(dir);
}
void SCPackageMgr::addFile(const QString &path)
{
    m_files.push_back(path);
}
void SCPackageMgr::package(const QString &packagePath, const QString &passWord, int level)
{
    SCPackageWorker *worker = new SCPackageWorker(m_files, m_dirs);
    connect(worker, SIGNAL(packageProgress(const QString&,const QString&)), this, SIGNAL(packageProgress(const QString&,const QString&)));
    worker->package(packagePath, passWord, level);
    m_tasks.push_back(worker);
}
void SCPackageMgr::unPackage(const QString &strPackageFilePath, const QString &strUnPackageDir, const QString &password)
{
    SCPackageWorker *worker = new SCPackageWorker();
    connect(worker, SIGNAL(unPackageProgress(const QString&,const QString&)), this, SIGNAL(unPackageProgress(const QString&,const QString&)));
    worker->unPackage(strPackageFilePath, strUnPackageDir, password);
    m_tasks.push_back(worker);
}
void SCPackageMgr::unPackFileFromPackge(const QString &strPackageFilePath, const QString &strUnPackageDir, const QString &fileNameInPackage, const QString &password)
{
    SCPackageWorker *worker = new SCPackageWorker();
    connect(worker, SIGNAL(unPackageProgress(const QString&,const QString&)), this, SIGNAL(unPackageProgress(const QString&,const QString&)));
    worker->unPackFileFromPackge(strPackageFilePath, strUnPackageDir, fileNameInPackage, password);
    m_tasks.push_back(worker);
}
SCPackageMgr::SCPackageMgr()
{
}
SCPackageMgr::~SCPackageMgr()
{
    foreach (SCPackageWorker *worker, m_tasks) {
        if(NULL != worker){
            worker->quit();
            delete worker;
            worker = NULL;
        }
    }
}
void SCPackageWorker::package(const QString &packagePath, const QString &passWord, int level )
{
    m_WorkerType = PACKAGE_TYPE;
    m_strPackageFilePath = packagePath;
    m_strPw = passWord;
    m_nlevel = level;
    start();
}
void SCPackageWorker::unPackage(const QString &strPackageFilePath, const QString &strUnPackageDir, const QString &password)
{
     m_WorkerType = UNPACKAGE_TYPE;
     m_strPackageFilePath = strPackageFilePath;
     m_strUnPackageDir = strUnPackageDir;
     m_strPw = password;
     start();
}
void SCPackageWorker::unPackFileFromPackge(const QString &strPackageFilePath,
                                        const QString &strUnPackageDir,
                                        const QString &fileNameInPackage,
                                        const QString &password)
{
    m_WorkerType = UNPACKAGE_ONE_TYPE;
    m_strPackageFilePath = strPackageFilePath;
    m_strUnPackageDir = strUnPackageDir;
    m_strUnPackageOneFileName = fileNameInPackage;
    m_strPw = password;
    start();
}
void SCPackageWorker::run()
{
    switch (m_WorkerType) {
    case PACKAGE_TYPE:
        startPackage();
        break;
    case UNPACKAGE_TYPE:
        startUnPackage();
        break;
    case UNPACKAGE_ONE_TYPE:
        startUnPacgeOne();
        break;
    default:
        break;
    }
}
SCPackageWorker::SCPackageWorker(const FileList &fileList, const DirList &dirList)
{
    m_dirs = dirList;
    m_files = fileList;
}
void SCPackageWorker::packageByDir(zipFile zf, const QString &strPath, const QString &parentDir, const QString &passWord, int level)
{
   QString strRelativePath;
   QDir dir(strPath);
   foreach(QFileInfo mfi , dir.entryInfoList())
   {
     if(mfi.fileName()=="." || mfi.fileName() == "..")
           continue;
     if (parentDir == "")
         strRelativePath = mfi.fileName();
     else
         strRelativePath = parentDir + "/" + mfi.fileName(); //生成在zip檔案中的相對路徑
     if(mfi.isFile())
     {
         packageByFile(zf, strRelativePath, mfi.filePath(), passWord, level);
     }
     else
     {
         packageByFile(zf, strRelativePath, NULL, passWord, level);
         emit progressInfo(QString::fromLocal8Bit("正在打包目錄:")+strRelativePath);
         packageByDir(zf, mfi.filePath(), strRelativePath, passWord, level); //遞歸收集子目錄檔案
     }
   }
}
void SCPackageWorker::packageByFile(zipFile zf,  const QString &fileNameInPackage, const QString &filePath, const QString &passWord, int level)
{
     FILE* srcfp = NULL;
      //初始化寫入zip的檔案資訊
      zip_fileinfo zi;
      zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
      zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
      zi.dosDate = 0;
      zi.internal_fa = 0;
      zi.external_fa = 0;
      //如果srcFile為空,加入空目錄
      char new_file_name[MAX_PATH];
      memset(new_file_name, 0, sizeof(new_file_name));
      strcat(new_file_name, fileNameInPackage.toLocal8Bit().data());
      if (filePath.isEmpty())
      {
          strcat(new_file_name, "/");
      }
      //在zip檔案中建立新檔案
       zipOpenNewFileInZip3_64(zf, new_file_name, &zi, NULL, 0, NULL, 0, NULL, Z_DEFLATED, level, 0, -MAX_WBITS, DEF_MEM_LEVEL,
             Z_DEFAULT_STRATEGY, passWord.toLocal8Bit().data(), 0, 0);
       //zipOpenNewFileInZip(zf, new_file_name, &zi, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION);
      if (!filePath.isEmpty())
      {
          //打開源檔案
          srcfp = fopen(filePath.toLocal8Bit().data(), "rb");
          if (srcfp == NULL)
          {
              zipCloseFileInZip(zf); //關閉zip檔案
              return;
          }
          //讀入源檔案并寫入zip檔案
          char buf[100*1024]; //buffer
          int numBytes = 0;
          while( !feof(srcfp) )
          {
              numBytes = fread(buf, 1, sizeof(buf), srcfp);
              zipWriteInFileInZip(zf, buf, numBytes);
              if( ferror(srcfp) )
                  break;
          }
          //關閉源檔案
          fclose(srcfp);
      }
      //關閉zip檔案
      //zipCloseFileInZip(zf);
    QString currentProgress = QString::number(qMax(1, qMin(100*(++m_nLoopCount)/m_nTasks, 99)));
    if(m_strLastProgress != currentProgress)
    {
        emit packageProgress(m_strPackageFilePath,  currentProgress);
        m_strLastProgress = currentProgress;
    }
    emit progressInfo(QString::fromLocal8Bit("正在打封包件:")+new_file_name);
}
void SCPackageWorker::getDirFileCount(const QString &dirPath, int &count)
{
    if(dirPath.isEmpty())
        return;
    QDir dir(dirPath);
     foreach(QFileInfo mfi , dir.entryInfoList())
     {
       if(mfi.isFile())
       {
           count++;
       }else
       {
           if(mfi.fileName()=="." || mfi.fileName() == "..")
               continue;
           getDirFileCount(mfi.absoluteFilePath(), count);
       }
     }
}
void SCPackageWorker::startPackage()
{
    if(m_dirs.count() == 0 && m_files.count() == 0)
        return;
    zipFile newZipFile = zipOpen(m_strPackageFilePath.toLocal8Bit().data(), APPEND_STATUS_CREATE); //建立zip檔案
    if (newZipFile == NULL)
    {
        emit progressInfo(QString::fromLocal8Bit("建立打封包件失敗:")+m_strPackageFilePath);
        return ;
    }
    //總任務量
    m_nTasks = m_files.count();
    //emit packageProgress(m_strPackageFilePath, QString::fromLocal8Bit("正在計算檔案個數....."));
    foreach (const QString path, m_dirs) {
         getDirFileCount(path, m_nTasks);
    }
    //完成一個任務占用的%
    m_nLoopCount = 0;
    //打封包件夾
    foreach (const QString dir, m_dirs) {
        packageByDir(newZipFile, dir, "", m_strPw, m_nlevel);
    }
    //打封包件
    foreach (const QString path, m_files) {
        QFileInfo fileInfo(path);
        packageByFile(newZipFile, fileInfo.fileName(), fileInfo.filePath(), m_strPw, m_nlevel);
    }
    //關閉zip檔案
    emit packageProgress(m_strPackageFilePath, "100");
    zipCloseFileInZip(newZipFile);
    zipClose(newZipFile, NULL); //關閉zip檔案
}
void SCPackageWorker::startUnPacgeOne()
{
     //打開
      unzFile zFile = unzOpen64(m_strPackageFilePath.toLocal8Bit().data());
     if (zFile == NULL)
     {
         qDebug()<<QString::fromLocal8Bit("檔案打開失敗")<<m_strPackageFilePath;
         return ;
     }
     //定位檔案
     int err = unzLocateFile(zFile, m_strUnPackageOneFileName.toLocal8Bit().data(), 0);
     if (UNZ_OK != err)
     {
         qDebug() << "unzLocateFile failed!err:" << err;
         return ;
     }
     //擷取目前檔案資訊
     unsigned int BufSize = 512;
     char *szFileName_WithPath = new char[BufSize];
     unz_file_info zFileInfo;
     if (UNZ_OK != unzGetCurrentFileInfo(zFile, &zFileInfo, szFileName_WithPath, BufSize, NULL, 0, NULL, 0))
     {
         qDebug()<<QString::fromLocal8Bit("擷取檔案資訊失敗");
         return;
     }
     //打開目前檔案
     if (UNZ_OK != unzOpenCurrentFile(zFile))
     {
         qDebug()<<QString::fromLocal8Bit("打開目前檔案失敗");
         return;
     }
     //定義一個fstream對象,用來寫入檔案
     QString strFileName = m_strUnPackageDir+"\\"+m_strUnPackageOneFileName;
     fstream file;
     file.open(strFileName.toLocal8Bit().data(), ios_base::out | ios_base::binary);
     //解壓檔案,到fileData中
     unsigned char* fileData = new unsigned char[zFileInfo.uncompressed_size];
     memset(fileData , 0,zFileInfo.uncompressed_size);
     err = unzReadCurrentFile(zFile, (voidp)fileData, zFileInfo.uncompressed_size);
     if (err < 0)
     {
         qDebug()<<QString::fromLocal8Bit("讀取檔案資訊失敗");
         return;
     }
     //寫入檔案
     file.write((const char *)fileData, zFileInfo.uncompressed_size);
     file.close();
     unzClose(zFile);
     //釋放資源
     delete[] szFileName_WithPath;
     szFileName_WithPath = NULL;
     delete[] fileData;
     fileData = NULL;
}
void SCPackageWorker::startUnPackage()
{
    int nReturnValue;
    //打開zip檔案
    unzFile unzfile = unzOpen64(m_strPackageFilePath.toLocal8Bit().data());
    if (unzfile == NULL)
    {
        emit progressInfo(QString::fromLocal8Bit("打開檔案失敗:")+m_strPackageFilePath);
        return;
    }
    //擷取zip檔案的資訊
    unz_global_info64* pGlobalInfo = new unz_global_info64;
    nReturnValue = unzGetGlobalInfo64(unzfile, pGlobalInfo);
    if (nReturnValue != UNZ_OK)
    {
        emit progressInfo(QString::fromLocal8Bit("擷取打封包件資訊失敗:")+m_strPackageFilePath);
        return;
    }
    //解析zip檔案
    unz_file_info64* pFileInfo = new unz_file_info64;
    char szZipFName[MAX_PATH];
    //任務總量
    int nTasks = pGlobalInfo->number_entry;
    //完成一個任務占用的%
    //存放從zip中解析出來的内部檔案名
    for (int i = 0; i<nTasks; i++)
    {
        //解析得到zip中的檔案資訊
        nReturnValue = unzGetCurrentFileInfo64(unzfile, pFileInfo, szZipFName, MAX_PATH,
            NULL, 0, NULL, 0);
        if (nReturnValue != UNZ_OK)
        {
            emit progressInfo(QString::fromLocal8Bit("擷取檔案資訊失敗:")+szZipFName);
            return;
        }
        qDebug()<<szZipFName;
        //判斷是檔案夾還是檔案
        if(QString(szZipFName).right(1) == "/")
        {
            QString strDiskPath = m_strUnPackageDir+ "/" + szZipFName;
            strDiskPath = strDiskPath.replace("/", "\\");
            CreateDirectoryA(strDiskPath.toLocal8Bit().data(), NULL);
            emit progressInfo(QString::fromLocal8Bit("正在建立目錄:")+strDiskPath);
        }
        else
        {
            //建立檔案
            QString strDiskFile = m_strUnPackageDir + "/";
            strDiskFile += szZipFName;
            strDiskFile = strDiskFile.replace("\\", "/");
            HANDLE hFile = CreateFile(strDiskFile.toStdWString().c_str(), GENERIC_WRITE,
                0, NULL, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
            if (hFile == INVALID_HANDLE_VALUE)
            {
                emit progressInfo(QString::fromLocal8Bit("建立檔案失敗:")+strDiskFile);
                qDebug()<<QString::fromLocal8Bit("建立檔案失敗:")+strDiskFile;
                return;
            }
            //打開檔案
            nReturnValue = unzOpenCurrentFilePassword(unzfile, m_strPw.toLocal8Bit().data());
            if (nReturnValue != UNZ_OK)
            {
                emit progressInfo(QString::fromLocal8Bit("密碼錯誤,解密檔案失敗:")+strDiskFile);
                CloseHandle(hFile);
                return;
            }
            //讀取檔案
            const int BUFFER_SIZE = 4096;
            char szReadBuffer[BUFFER_SIZE];
            emit progressInfo(QString::fromLocal8Bit("正在寫入檔案内容"));
            while (TRUE)
            {
                memset(szReadBuffer, 0, BUFFER_SIZE);
                int nReadFileSize = unzReadCurrentFile(unzfile, szReadBuffer, BUFFER_SIZE);
                if (nReadFileSize < 0)                //讀取檔案失敗
                {
                    unzCloseCurrentFile(unzfile);
                    CloseHandle(hFile);
                    return;
                }
                else if (nReadFileSize == 0)            //讀取檔案完畢
                {
                    unzCloseCurrentFile(unzfile);
                    CloseHandle(hFile);
                    break;
                }
                else                                //寫入讀取的内容
                {
                    DWORD dWrite = 0;
                    BOOL bWriteSuccessed = WriteFile(hFile, szReadBuffer, BUFFER_SIZE, &dWrite, NULL);
                    if (!bWriteSuccessed)
                    {
                        unzCloseCurrentFile(unzfile);
                        CloseHandle(hFile);
                        return;
                    }
                }
            }
            emit progressInfo(QString::fromLocal8Bit("檔案建立完成"));
        }
        unzGoToNextFile(unzfile);
        QString currentProgress = QString::number(qMax(1, qMin(100*(i+1)/nTasks, 99)));
        if(m_strLastProgress != currentProgress)
        {
            emit unPackageProgress(m_strPackageFilePath,  currentProgress);
            m_strLastProgress = currentProgress;
        }
    }
    //關閉
    if (unzfile)
    {
        unzClose(unzfile);
    }
    emit unPackageProgress(m_strPackageFilePath, "100");
}
           

使用方法:

進度擷取:連接配接信号即可

connect(&SCPackageMgr::instance(),SIGNAL(packageProgress(constQString&,constQString&)),this,SLOT(slotPackageProgress(constQString&,constQString&)));

connect(&SCPackageMgr::instance(),SIGNAL(unPackageProgress(QString,QString)),this,SLOT(slotUnPackageProgress(constQString&,constQString&)));

打包:

//任務一

    SCPackageMgr::instance().addDir("F:\\SCEarthEngine");
    SCPackageMgr::instance().addFile("F:\\Observer.h");
    SCPackageMgr::instance().package("F:\\1.zip", "123456", 5);
   //任務二
   SCPackageMgr::instance().clear();
   SCPackageMgr::instance().addDir("F:\\ScEarthEngineDAI");
   SCPackageMgr::instance().package("F:\\3.zip", "123456", 5);
   //任務=三
     SCPackageMgr::instance().clear();
  SCPackageMgr::instance().addDir("F:\\VisualizationsEngine");
    SCPackageMgr::instance().package("F:\\2.zip", "123456", 5);
           

解包

SCPackageMgr::instance().unPackage("f:\\1.zip","f:\\test","123456");

從包中解壓一個檔案:

SCPackageMgr::instance().unPackFileFromPackge("f:\\1.zip","f:\\test","Observer.h","");
           

源碼中使用了C/C++相關方法實作檔案的讀寫,可以換成Qt相關的類進行,我比較懶沒改,沒有整理,建立目錄都使用的windows函數。有疑問可以交流。

類檔案下載下傳位址:http://pan.baidu.com/s/1bYWRee  密碼:s344