純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; }