檔案及檔案夾打包解包
功能
- 對多個檔案打包
- 對單個檔案夾(可包含多個子檔案及子檔案夾)打包
說明見頭檔案注釋
#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---" ;
}