純C/C++ 自製打包程式 [CB_CAB_PROJECT]

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

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *