c++文件打包工具实现

时间:2024-11-08 09:33:44

没事做就来写一个打包的工具吧。很多是网络上面找的,只是我把他修改一下合并在一起。

// PacketFile.cpp : 定义控制台应用程序的入口点。

#include "stdafx.h"

#include "SerchAllFile.h"

#include "MyCab.h"

int _tmain(int argc, _TCHAR* argv[])

{


vector<string> vec_file;


vector<string>::iterator itemFileName;


char filePacketPath[MAX_PATH] = "E:\\huangyushi\\测试写的实例";


char filePutPath[MAX_PATH] = "d:\\fasdfasdf\\my.cab";


CSerchAllFile::getInstance()->get_filelist(filePacketPath, vec_file);

//--------------------打包过程--------------------


//声明对象


CMyCab mc;


//设置输出文件


mc.SetOutPutFile(filePutPath);


//添加要打包的文件


for (itemFileName=vec_file.begin(); itemFileName<vec_file.end(); itemFileName++)


{


mc.AddFile((*itemFileName).c_str());


}


//执行打包


mc.DoMakeCAB();

//--------------------解过程--------------------


//声明对象


CMyCab umc;


//执行解包


umc.DoUnCAB(filePutPath);

cin.clear();


cin.get();

return 0;

}

-----------------------------------------------------------------------------------------------------------------------

打包一个文件下面的文件,我要先要做的就是遍历查找里面的文件,并将文件全部记录起来(通过get_filelist()方法我们可以得到对应的文件路径并保存到一个vector里面)

#pragma once

#include <string>
#include <vector>
#include <fstream>
#include <windows.h>
#include <iostream>
#include <conio.h>

using namespace std;

class CSerchAllFile
{
public:
CSerchAllFile(void);
~CSerchAllFile(void);
static CSerchAllFile *getInstance();

public:
/*void find(char *lpPath);
void _find(string path);*/

void get_filelist(char *foldname,vector<string> &filelist);
void ReadFile(const char* fileName);
void WriteFile(string fileName);
};

#include "StdAfx.h"
#include "SerchAllFile.h"

static CSerchAllFile* instance;

CSerchAllFile::CSerchAllFile(void)
{
}

CSerchAllFile::~CSerchAllFile(void)
{
}

CSerchAllFile* CSerchAllFile::getInstance()
{
if (instance == NULL)
{
instance = new CSerchAllFile();
}

return instance;
}

//遍历文件夹下的文件名列表(包括嵌套文件夹)
void CSerchAllFile::get_filelist(char *foldname,vector<string> &filelist)
{
HANDLE hFind;
WIN32_FIND_DATA fileData;
string line;
char fn[MAX_PATH];
char tmpfn[MAX_PATH];
strcpy(fn,foldname);

//需要对文件夹名的字符串进行处理
if(fn[strlen(fn) -1] != '\\' )
{
strcat(fn, "\\");
}

//留意顺序,此时fn已加入"\\"
strcpy(tmpfn,fn);
//不加*会出错!
strcat(fn, "*");

hFind = FindFirstFile(fn, &fileData);
FindNextFile(hFind, &fileData);
while(FindNextFile(hFind, &fileData))
{
//如果扫描到的当前为文件夹
if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if(fileData.cFileName[0]!='.')
{
char szFile[MAX_PATH];
strcpy(szFile,tmpfn);
strcat(szFile,fileData.cFileName);
get_filelist(szFile,filelist);
}
}
//扫描到文件
else
{
line = (string)tmpfn;
line+=fileData.cFileName;
/*if (line.find(".h",0)!=string::npos)
{
filelist.push_back(line);
}
else
{
continue;
}*/
filelist.push_back(line);
}
//cout<<line<<endl;
}
}

---------------------------------------------------------------------------------------------------------------------

#pragma once

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <error.h>
#include <direct.h>
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];//文件名
};

class CMyCab
{
private:
FileHead fh;//文件头
char ObjectFilePathName[MAX_PATH];//生成打包文件位置及名称

public:
CMyCab(void);
~CMyCab(void);

//添加文件到包内
void AddFile(const char * FilePathName);
//设置打包输出文件
void SetOutPutFile(char * OutFile);
//获取文件大小(传入以二进制方式打开的文件指针)
long GetFileSize(FILE *pf);
//制作打包文件
void DoMakeCAB();
//解包(为了节省时间不写错误处理了,可以根据上面自己添加)
void DoUnCAB(char *CabFilePathName);

private:
//显示打包内文件信息
void printCAB();
//创建文件夹
void CheckTargetPath(string targetPath);
};

#include "StdAfx.h"
#include "MyCab.h"

CMyCab::CMyCab(void)
{
memset(&fh,0x0,sizeof(fh));
memset(ObjectFilePathName,0x0,sizeof(ObjectFilePathName));
}

CMyCab::~CMyCab(void)
{
}

//添加文件到包内
void CMyCab::AddFile(const char * FilePathName)
{
if ( fh.FileCount >= MAX_FILE_COUNT - 1 )
{
cout<<"最多支持"<<MAX_FILE_COUNT<<"个文件"<<endl;
return;
}
strcpy(fh.FileName[fh.FileCount],FilePathName);
fh.FileCount++;
}

//设置打包输出文件
void CMyCab::SetOutPutFile(char * OutFile)
{
memset(ObjectFilePathName,0x0,sizeof(ObjectFilePathName));
strcpy(ObjectFilePathName,OutFile);
}

//获取文件大小(传入以二进制方式打开的文件指针)
long CMyCab::GetFileSize(FILE *pf)
{
//指针移到文件尾
fseek(pf,0,/*SEEK_END*/ 2);
return ftell(pf);
}

//制作打包文件
void CMyCab::DoMakeCAB()
{
if ( fh.FileCount < 1 )
{
cout<<"没有文件添加到打包"<<endl;
return;
}
if ( strlen(ObjectFilePathName) < 1 )
{
cout<<"没有指定打包文件输出位置"<<endl;
return;
}

FILE *pOutFile = NULL;
FILE *pWorkFile = NULL;

//获取所有文件大小
for ( int i = 0 ; i < fh.FileCount ; i++ )
{
pWorkFile = fopen(fh.FileName[i],"rb");
if ( NULL == pWorkFile )
{
cout<<"文件:"<<fh.FileName[i]<<"无法读取["<<strerror(errno)<<"]"<<endl;
return;
}
fh.FileLen[i] = GetFileSize(pWorkFile);
fclose(pWorkFile);
}

//检查是否有对应的文件夹
CheckTargetPath(ObjectFilePathName);
//开始合并写文件
pOutFile = fopen(ObjectFilePathName,"wb");
if ( NULL == pOutFile )
{
cout<<"输出文件创建失败["<<strerror(errno)<<"]"<<endl;
return;
}

//写入文件头
fwrite(&fh,sizeof(fh),1,pOutFile);
//写入各文件
for ( int i = 0 ; i < fh.FileCount ; i++ )
{
unsigned char *pTmpData = NULL;
pWorkFile = fopen(fh.FileName[i],"rb");
if ( NULL == pWorkFile )
{
cout<<"文件:"<<fh.FileName[i]<<"无法读取["<<strerror(errno)<<"]"<<endl;
fclose(pWorkFile);
fclose(pOutFile);
return;
}
pTmpData = new unsigned char[fh.FileLen[i]];
fread(pTmpData,fh.FileLen[i],1,pWorkFile);
if ( ferror(pWorkFile) )
{
cout<<"文件:"<<fh.FileName[i]<<"无法读取["<<strerror(errno)<<"]"<<endl;
fclose(pWorkFile);
fclose(pOutFile);
return;
}
fwrite(pTmpData,fh.FileLen[i],1,pOutFile);
if ( ferror(pOutFile) )
{
cout<<"文件:"<<ObjectFilePathName<<"无法写入["<<strerror(errno)<<"]"<<endl;
fclose(pWorkFile);
fclose(pOutFile);
return;
}
delete [] pTmpData;
fclose(pWorkFile);
}

fclose(pOutFile);
cout<<"打包完成"<<endl;
}

//解包(为了节省时间不写错误处理了,可以根据上面自己添加)
void CMyCab::DoUnCAB(char *CabFilePathName)
{
FILE *pCAB = NULL;
FILE *pWork = NULL;

pCAB = fopen(CabFilePathName,"rb");

//读文件头
memset(&fh,0x0,sizeof(fh));
fread(&fh,sizeof(fh),1,pCAB);

printCAB();

//解包的所有文件放到当前目录下
for ( int i = 0 ; i < fh.FileCount ; i++ )
{
unsigned char *pTmpData = NULL;
pTmpData = new unsigned char[fh.FileLen[i]];
fread(pTmpData,fh.FileLen[i],1,pCAB);
//只取文件名,不要生成文件的路径名
char tmpFileName[MAX_PATH];
string str = "E:\\huangyushi\\测试写的实例\\";
string aaa;
aaa.assign(fh.FileName[i] ,strlen(fh.FileName[i]) );
const char *chaaaaa = aaa.replace(0, str.length(), "\\").c_str();
char ptmpC[MAX_PATH];
strcpy(ptmpC, chaaaaa);

memset(tmpFileName,0x0,sizeof(tmpFileName));
strcpy(tmpFileName,ptmpC+1);
//取CAB文件路径
char tmpPathName[MAX_PATH];
memset(tmpPathName,0x0,sizeof(tmpPathName));
strcpy(tmpPathName,CabFilePathName);
char* tmpC = tmpPathName + strlen(tmpPathName);
while('\\' != *tmpC)
{
tmpC--;
}
tmpC++;
*tmpC = '\0';
strcat(tmpPathName,tmpFileName);

pWork = fopen(tmpPathName,"wb");
if (pWork == NULL)
{
CheckTargetPath(tmpPathName);
pWork = fopen(tmpPathName,"wb");
}
fwrite(pTmpData,fh.FileLen[i],1,pWork);
fclose(pWork);
delete [] pTmpData;
}

fclose(pCAB);
}

//显示打包内文件信息
void CMyCab::printCAB()
{
cout<<"文件内信息如下:"<<endl;
cout<<"文件总数:"<<fh.FileCount<<endl;
for ( int i = 0 ; i < fh.FileCount ; i++ )
{
cout<<fh.FileName[i]<<"\t\t\t\t"<<fh.FileLen[i]<<"字节"<<endl;
}
}

//创建文件夹
void CMyCab::CheckTargetPath(string targetPath)
{
//Log &log = Log::getLog("main", "CheckTargetPath");
int e_pos = targetPath.length();
int f_pos = targetPath.find("\\",0);
string subdir;
do
{
e_pos = targetPath.find("\\",f_pos+2);
if(e_pos != -1)
{
subdir = targetPath.substr(0,e_pos);
if(_mkdir(subdir.c_str())==0)
printf( "creat success %s",subdir.c_str());
else 
printf("creat fail %s",subdir.c_str());
}
f_pos = e_pos;
}while(f_pos!=-1);
}