天天看點

檔案及檔案夾打包解包

檔案及檔案夾打包解包

功能

  • 對多個檔案打包
  • 對單個檔案夾(可包含多個子檔案及子檔案夾)打包

說明見頭檔案注釋

#ifndef ZOLFILEPACK_H
#define ZOLFILEPACK_H

#include <string>
#include <vector>
#include <QDir>
#include <QFileInfo>
#include <QFileInfoList>
using namespace std;

//最多打封包件個數
#define MAX_FILE_COUNT  1024
//最大路徑字元長度
#define MAX_PATH   260

//檔案頭
struct FileHead
{
    unsigned int FileCount;//檔案個數
    unsigned int FileLen[MAX_FILE_COUNT];//檔案大小
    char FileName[MAX_FILE_COUNT][MAX_PATH];//檔案名
    char fileDir[MAX_PATH]; //檔案夾路徑
};

class ZolFilePack
{
public:
    ZolFilePack();

    /**
    * @brief 檔案打包
    * @param 打包輸出檔案
    * @return bool
    */
    bool PackFileAndDirectory(const string& outputfilename);
    /**
    * @brief 檔案解包
    * @param 打封包件、輸出檔案夾路徑
    * @return bool
    */
    bool UnPackFileAndDirectory(const string& inputzipfile, const string& outputpath);
    /**
    * @brief 擷取檔案夾子檔案
    * @param 檔案夾路徑、子檔案集合
    * @return void
    */
    void GetAllFiles(const QString  &path,vector<string>& files);
    //增加打封包件
    void AddFile(const char * FilePathName);
    //增加打封包件夾
    void addDirectory( const string& directories);
    //擷取檔案大小
    long GetFileSize(FILE *pf);

private:
    //輸出檔案資訊
    void printFileInfo();

private:
    FileHead m_fileh;//檔案頭

};


#endif // ZOLFILEPACK_H

           

cpp檔案

#include "zolfilepack.h"
#include <QDebug>

ZolFilePack::ZolFilePack()
{
    memset(&m_fileh,0x0,sizeof(m_fileh));
}

void ZolFilePack::GetAllFiles(const QString &path, vector<string> &files)
{
    QDir dir(path);
    if (!dir.exists())
        return ;
    dir.setFilter(QDir::Dirs|QDir::Files);
    dir.setSorting(QDir::DirsFirst);
    QFileInfoList list = dir.entryInfoList();
    int i=0;
    do{
        QFileInfo fileInfo = list.at(i);
        if(fileInfo.fileName()=="."|fileInfo.fileName()=="..")
        {
            i++;
            continue;
        }
        bool bisDir=fileInfo.isDir();
        if(bisDir)
        {
            QString dirpath = fileInfo.path() +"/" + fileInfo.fileName();
            //qDebug() << "dirpath" << dirpath;
            files.push_back(dirpath.toStdString());
            GetAllFiles(fileInfo.filePath(),files);
        }
        else{
            QString dirpath = fileInfo.path() +"/" + fileInfo.fileName();
            //qDebug() << "dirpath" << dirpath;
            if((fileInfo.fileName().split('.').last()) != "dat")
                files.push_back(dirpath.toStdString());
        }
        i++;
    }while(i<list.size());
}

long ZolFilePack::GetFileSize(FILE *pf)//擷取檔案大小(傳入以二進制方式打開的檔案指針)
{
    //指針移到檔案尾
    fseek(pf,0,SEEK_END);
    return ftell(pf);
}

void ZolFilePack::AddFile(const char * FilePathName)
{

    if ( m_fileh.FileCount >= MAX_FILE_COUNT - 1 )
    {
        qDebug()<<"最多支援"<<MAX_FILE_COUNT<<"個檔案";
        return;
    }
    strcpy(m_fileh.FileName[m_fileh.FileCount],FilePathName);
    m_fileh.FileCount++;
}

void ZolFilePack::addDirectory(const string &directories)
{
    strcpy(m_fileh.fileDir,directories.c_str());

    int subNum = 0;
    vector<string>AllSubFiles;
    GetAllFiles(QString::fromStdString(directories),AllSubFiles);
    subNum = AllSubFiles.size();

    for (int j=0;j<AllSubFiles.size();j++)
    {
        QFileInfo fileinfo;
        fileinfo.setFile(QString::fromStdString(AllSubFiles[j]));
        if(fileinfo.isFile())
        {
            const char *tmpFile=AllSubFiles[j].c_str();
            AddFile(tmpFile);
        }
        else {
            const char *tmpDir=AllSubFiles[j].c_str();
            AddFile(tmpDir);
        }
    }
}

bool ZolFilePack::PackFileAndDirectory(const string &outputfilename)
{
    if ( m_fileh.FileCount < 1 )
    {
        qDebug()<<"沒有檔案添加到打包";
        return false;
    }

    FILE * pOutFile = nullptr;
    FILE * pWorkFile = nullptr;
    pOutFile = fopen(outputfilename.c_str(), "wb");

    if (pOutFile == nullptr)
    {
        qDebug() << "打包:檔案打開失敗!";
        return false;
    }

    //擷取所有檔案大小
    for ( int i = 0 ; i < m_fileh.FileCount ; i++ )
    {
        QFileInfo file(m_fileh.FileName[i]);
        if(file.isFile()){
            pWorkFile = fopen(m_fileh.FileName[i],"rb");
            if ( nullptr == pWorkFile )
            {
                qDebug()<<"檔案:"<<m_fileh.FileName[i]<<"無法讀取["<<strerror(errno)<<"]";
                return false;
            }
            m_fileh.FileLen[i] = GetFileSize(pWorkFile);
            fclose(pWorkFile);
        }
    }

    //寫入檔案頭
    fwrite(&m_fileh,sizeof(m_fileh),1,pOutFile);

    qDebug() << "打包:檔案數---" << m_fileh.FileCount;

    for (size_t i = 0; i < m_fileh.FileCount; i++)
    {
        QFileInfo file(m_fileh.FileName[i]);
        if(file.isFile()){
            pWorkFile = fopen(m_fileh.FileName[i],"rb");
            if ( nullptr == pWorkFile )
            {
                qDebug()<<"檔案:"<<m_fileh.FileName[i]<<"無法讀取["<<strerror(errno)<<"]";
                fclose(pWorkFile);
                fclose(pOutFile);
                return false;
            }
            unsigned char *eachFile = nullptr;
            eachFile = new unsigned char[m_fileh.FileLen[i]];

            //讀取
            fread(eachFile, m_fileh.FileLen[i], 1, pWorkFile);
            if ( ferror(pWorkFile) )
            {
                qDebug()<<"檔案:"<< pWorkFile <<"無法讀取["<<strerror(errno)<<"]";
                fclose(pWorkFile);
                fclose(pOutFile);
                return false;
            }

            //寫入
            fwrite(eachFile, m_fileh.FileLen[i], 1, pOutFile);
            if ( ferror(pOutFile))
            {
                qDebug()<<"檔案:"<<pOutFile<<"無法寫入["<<strerror(errno)<<"]";
                fclose(pWorkFile);
                fclose(pOutFile);
                return false;
            }

            delete [] eachFile;
            fclose(pWorkFile);
        }

    }
    fclose(pOutFile);
    return true;
}

bool ZolFilePack::UnPackFileAndDirectory(const string& inputzipfile, const string& outputpath)
{
    FILE *rfp = nullptr;
    rfp = fopen(inputzipfile.c_str(), "rb");

    if (rfp == nullptr)
    {
        qDebug() << "解包:檔案打開失敗!";
        return false;
    }

    //讀檔案頭
    memset(&m_fileh,0x0,sizeof(m_fileh));
    fread(&m_fileh,sizeof(m_fileh),1,rfp);

    //輸出檔案資訊
    printFileInfo();

    qDebug() << "解包:檔案打開個數!" << m_fileh.FileCount;

    if(m_fileh.fileDir != ""){//檔案夾
        for (size_t i = 0; i < m_fileh.FileCount; i++)
        {
            unsigned char *pTmpData = nullptr;
            pTmpData = new unsigned char[m_fileh.FileLen[i]];
            fread(pTmpData,m_fileh.FileLen[i],1,rfp);//可以不借助緩沖區

            //相對檔案夾的路徑名
            string tmpFileName  = m_fileh.FileName[i];
            tmpFileName = tmpFileName.substr(strlen(m_fileh.fileDir),MAX_PATH);

            string path_file;
            if (strstr(tmpFileName.c_str(), ".") == nullptr)
            {
                path_file = outputpath + '/' + tmpFileName;
                QDir targetDir(QString::fromStdString(path_file));
                if(!targetDir.exists()){    /* 如果目标目錄不存在,則進行建立 */
                    if(!targetDir.mkdir(targetDir.absolutePath())) {
                        return false;
                    }
                }
            }
            else {
                path_file = outputpath + '/' + tmpFileName; //path_file:全路徑

                FILE *unpackFile = nullptr;
                unpackFile = fopen(path_file.c_str(), "wb");

                if (unpackFile == nullptr)
                {
                    qDebug() << "檔案:檔案建立失敗!";
                    return false;
                }

                fwrite(pTmpData, m_fileh.FileLen[i], 1, unpackFile);
                fclose(unpackFile);
            }
        }
    }
    else {
        qDebug() << "檔案:檔案處理!";
        for (size_t i = 0; i < m_fileh.FileCount; i++)
        {
            unsigned char *pTmpData = nullptr;
            pTmpData = new unsigned char[m_fileh.FileLen[i]];
            fread(pTmpData,m_fileh.FileLen[i],1,rfp);//可以不借助緩沖區

            //隻取檔案名,不要生成檔案的路徑名
            char tmpFileName[MAX_PATH];
            char *ptmpC = m_fileh.FileName[i] + strlen(m_fileh.FileName[i]);
            while( '/' != *ptmpC)
            {
                ptmpC--;
            }
            memset(tmpFileName,0x0,sizeof(tmpFileName));
            strcpy(tmpFileName,ptmpC+1);

            string path_file = outputpath + '/' + tmpFileName; //path_file:全路徑

            FILE *unpackFile = nullptr;
            unpackFile = fopen(path_file.c_str(), "wb");

            if (unpackFile == nullptr)
            {
                qDebug() << "檔案:檔案建立失敗!";
                return false;
            }

            fwrite(pTmpData, m_fileh.FileLen[i], 1, unpackFile);
            fclose(unpackFile);
        }
    }
    return true;
}

void ZolFilePack::printFileInfo()
{

    qDebug()<<"檔案内資訊如下:";
    qDebug()<<"檔案總數:"<<m_fileh.FileCount;
    qDebug()<<"檔案夾路徑:"<< QString::fromStdString(m_fileh.fileDir);
    for ( int i = 0 ; i < m_fileh.FileCount ; i++ )
    {
        qDebug()<<m_fileh.FileName[i]<<"\t\t\t\t"<<m_fileh.FileLen[i]<<"位元組";
    }
}

           

使用:

檔案打包

FilePack myfile;
    myfile.AddFile("F:/mycabs/1234562.jpg");
    myfile.AddFile("F:/mycabs/HaxLogs2.txt");
    myfile.PackFileAndDirectory("F:/mycabs/data.dat");
	  if(myfile.UnPackFileAndDirectory("F:/mycabs/data.dat","F:/mycabs"))
	   {
	       qDebug() << "UnPackFileAndDirectory sccess---" ;
	   }
    
           

檔案夾打包

FilePack myfile;
    myfile.addDirectory("F:/mycabs/packDirectory");
    myfile.PackFileAndDirectory("F:/mycabs/packDirectory/data.dat");

if(myfile.UnPackFileAndDirectory("F:/mycabs/packDirectory/data.dat","F:/mycabs/packDirectory"))
    {
        qDebug() << "UnPackFileAndDirectory sccess---" ;
    }
           

繼續閱讀