純C/C++ 自製打包程式 [CB_CAB_PROJECT]
純C/C++ 自製打包程式 [CB_CAB_PROJECT]
GITHUB: https://github.com/jash-git/CB_CAB_PROJECT.git
01.CB_CustomCAB
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#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];//檔案名
};
char gchrFileName[200],gchrPath[200];
char gchrFileExt[20];
void GetFileName(char *data);
long GetFileSize(FILE *pf);
int CheckTargetPath(string targetPath);
int main(int argc, char *argv[])
{
int i=0;
int intcase=-1;
FILE *pf='\0';
char buf[513];
char buf1[1024];
string strbuf;
FILE *pWorkFile = '\0';
FileHead fh;
FILE *pOutFile = '\0';
char chrFileListPath[512];
char chrCABFilePath[512];
char chrOuputPath[512];
unsigned char *pTmpData = NULL;
char tmpFileName[MAX_PATH];
FILE *pCAB = '\0';
char cwd[512];
cout << "Hello world!" << endl;
memset(cwd,0,sizeof(cwd));
if (getcwd(cwd, sizeof(cwd)) != NULL)//抓取目前程式路徑
{
cout << "Current working dir: " <<cwd<<endl;
}
if(argc<3)//argv[0]=名稱,argv[1]=case,argv[2]=filelist path/save cab path,argv[3]= save cab path/OuputPath
{
cout << "parameter error" << endl;
return -1;
}
else
{
cout << argv[1]<< endl;
intcase=atoi(argv[1]);//0:Make Cab,1:DoUnCAB
if((intcase==0)||(intcase==1))
{
memset(chrFileListPath,0,sizeof(char));
memset(chrCABFilePath,0,sizeof(char));
memset(chrOuputPath,0,sizeof(char));
switch(intcase)
{
case 0://0:Make Cab
strcpy(chrFileListPath,argv[2]);
strcpy(chrCABFilePath,argv[3]);
cout << "file list: " <<chrFileListPath << endl;
cout << "cab file: " <<chrCABFilePath << endl;
GetFileName(chrFileListPath);
memset(cwd,0,sizeof(cwd));
strcpy(cwd,gchrPath);//所有被打包檔案的所在路徑
break;
case 1://1:DoUnCAB
strcpy(chrCABFilePath,argv[2]);
strcpy(chrOuputPath,argv[3]);
cout << "cab file: " <<chrCABFilePath << endl;
cout << "ouput path: " <<chrOuputPath << endl;
break;
}
}
else
{
cout << "parameter error" << endl;
return -1;
}
}
if(intcase==0)//0:Make Cab
{
pf=fopen(chrFileListPath,"r");//pf=fopen("filelist.txt","r");
vector<string> vec_file;
vec_file.clear();
memset(buf,0,sizeof(buf));
while(fgets(buf,512,pf) != NULL)
{
buf[strlen(buf)-1]='\0';
memset(buf1,0,sizeof(buf1));
strcpy(buf1,cwd);
strcat(buf1,buf);
pWorkFile='\0';
pWorkFile= fopen(buf1,"rb");
if(pWorkFile!='\0')//確定檔案存在 & 可讀
{
vec_file.push_back(buf1);
fclose(pWorkFile);
pWorkFile='\0';
}
}
//當文件內的路徑存到結構體內,並抓取檔案大小
memset(&fh,0,sizeof(FileHead));
fh.FileCount=0;
for ( i = 0 ; i < vec_file.size() ; i++ )
{
strbuf=vec_file[i];
strcpy(buf, strbuf.c_str());
strcpy(fh.FileName[fh.FileCount],buf);
pWorkFile= fopen(fh.FileName[i],"rb");
fh.FileLen[i] = GetFileSize(pWorkFile);
fclose(pWorkFile);
pWorkFile = '\0';
//printf("%s,%ld\n",fh.FileName[i],fh.FileLen[i]);
fh.FileCount++;
}
//將所有指定檔案打包
//memset(chrCABFilePath,0,sizeof(char));
//strcpy(chrCABFilePath,"test.cab");
//*
pOutFile = fopen(chrCABFilePath,"wb");
fwrite(&fh,sizeof(fh),1,pOutFile);//寫入檔頭
for (i = 0 ; i < fh.FileCount ; i++ )
{
pWorkFile='\0';
pWorkFile = fopen(fh.FileName[i],"rb");
if ( NULL == pWorkFile )
{
fclose(pWorkFile);
fclose(pOutFile);
return -1;
}
pTmpData = new unsigned char[fh.FileLen[i]];
fread(pTmpData,fh.FileLen[i],1,pWorkFile);
if ( ferror(pWorkFile) )
{
fclose(pWorkFile);
fclose(pOutFile);
return -2;
}
fwrite(pTmpData,fh.FileLen[i],1,pOutFile);
if ( ferror(pOutFile) )
{
fclose(pWorkFile);
fclose(pOutFile);
return -3;
}
delete [] pTmpData;
pTmpData='\0';
fclose(pWorkFile);
}
fclose(pOutFile);
pOutFile='\0';
}
else
{
//*/
//將打包檔解開,放到指定路徑
//strcpy(chrCABFilePath,"D:\\Visual project code\\CB_CustomCAB\\test.cab");
//memset(chrOuputPath,0,sizeof(char));
//strcpy(chrOuputPath, "C:\\CAB_Buf");
if((chdir(chrOuputPath)==0)||(CheckTargetPath(chrOuputPath)==0))
{
pCAB = fopen(chrCABFilePath,"rb");
memset(&fh,0x0,sizeof(fh));
fread(&fh,sizeof(fh),1,pCAB);//讀取文件檔頭
for ( int i = 0 ; i < fh.FileCount ; i++ )
{
pTmpData = new unsigned char[fh.FileLen[i]];
fread(pTmpData,fh.FileLen[i],1,pCAB);
GetFileName(fh.FileName[i]);
memset(tmpFileName,0,sizeof(char));
sprintf(tmpFileName,"%s\\%s%s",chrOuputPath,gchrFileName,gchrFileExt);
pWorkFile = '\0';
pWorkFile = fopen(tmpFileName,"wb");
fwrite(pTmpData,fh.FileLen[i],1,pWorkFile);
fclose(pWorkFile);
delete [] pTmpData;
pTmpData='\0';
}
fclose(pCAB);
}
}
return 0;
}
//獲取檔大小(傳入以二進制方式打開的檔指針)
long GetFileSize(FILE *pf)
{
//指針移到檔案結尾
fseek(pf,0,/*SEEK_END*/ 2);
return ftell(pf);
}
void GetFileName(char *data)
{
gchrPath[0]='\0';
gchrFileName[0]='\0';
gchrFileExt[0]='\0';
int i,intcount;
int j=0;
int k=0;
char d;
intcount=strlen(data);//計算原本完整檔案路徑長度
for(i=(intcount-1);i>=0;i--)
{
if((data[i]!='/')&&(data[i]!='\\'))
{
d=data[i];
gchrPath[j]=d;
j++;
}
else
{
break;
}
}
gchrPath[j]='\0';
for(int i=0;i<j;i++)
{
if(i<(j-4))
{
gchrFileName[i]=gchrPath[j-i-1];
gchrFileName[i+1]='\0';
}
else
{
gchrFileExt[k]=gchrPath[j-i-1];
k++;
gchrFileExt[k]='\0';
}
}
gchrPath[0]='\0';
for(i=0;i<(intcount-j);i++)
{
gchrPath[i]=data[i];
}
gchrPath[(intcount-j)]='\0';
//cout<<chrPath<<"\n";
//cout<<chrFileName<<"\n";
}
int CheckTargetPath(string targetPath)
{
targetPath+="\\";//Bat內的路徑沒有最後的反斜線
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\n",subdir.c_str());
}
else
{
printf("creat fail %s\n",subdir.c_str());
}
}
f_pos = e_pos;
}while(f_pos!=-1);
return 0;
}
02.CB_createCAB
#ifndef CMYCAB_H
#define CMYCAB_H
#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);
};
#endif // CMYCAB_H
#include "CMyCab.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="d:\\";
string aaa;
aaa.assign(fh.FileName[i] ,strlen(fh.FileName[i]) );
const char *chaaaaa = aaa.replace(0, str.length(), "\\").c_str();
//printf("%s\n",chaaaaa);
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);
}
#ifndef CSERCHALLFILE_H
#define CSERCHALLFILE_H
#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);
};
#endif // CSERCHALLFILE_H
#include "CSerchAllFile.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;
}
}
#include <iostream>
#include "CSerchAllFile.h"
#include "CMyCab.h"
using namespace std;
int main()
{
cout << "Hello world!" << endl;
vector<string> vec_file;
vector<string>::iterator itemFileName;
char filePacketPath[MAX_PATH] = "D:\\VM_Win7\\net4_zip_test";//"D:\\sqliteadmin";
char filePutPath[MAX_PATH] = "D:\\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("C:\\my.cab");
return 0;
}