文件合并程序

来源:互联网 发布:徐州网络推广学校 编辑:程序博客网 时间:2024/06/04 00:43
文件合并程序
程序的功能
将一个目录中的指定的文件进行合并或者拆分。
处理规则是:将指定目录中的指定的文件形成一个文件列表,对该列表中的每一个文件进行读取,一条一条地将记录写入目的文件,当目的文件达到指定的数量的时候,关闭旧的目的文件,打开新的目的文件,继续处理原始的记录。最终的后果就是,如果原始文件的记录较少,该程序实现了文件合并,如果原始文件的记录数量较多,该程序实现了文件的拆分。
使用到的系统函数有:
获取文件目录中文件列表的办法;
取得当前程序进程号;
获取时间的办法;
C++中读写文件的办法;

一些宏的使用;

#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <dirent.h>#include <string.h>#include <time.h>#include <vector>#include <string>#include <fstream>using namespace std;/*编译方法AIX:xlC_r -g -w -q64 -qwarn64 -brtl -bhalt:5 -o mergeCdr mergeCdr.cpp发布的时候,去掉“-g”*//*版本号定义规则1 主版本号,用于较大的程序改动0 次版本号,用于较小的需求改动0 每次的修改的bug 更改次数1 总的发布次数第一次版本的发布信息为: Ver 1.0.0.1*//*版本修改历史:Ver 1.0.0.1 功能点:支持程序将指定目录中的指定的文件,复制并备份到指定的目录Ver 1.1.0.2 功能点:支持将目的文件设定最大行数*/#define __VER__ "Ver 1.1.0.2"const int FILE_NAME_LEN  = 256;//文件名的最大长度const int BUFFER_LEN = 4096;//清单中的一条记录的最大长度vector<string> vec_file;//用于存放需要处理的文件名称int nFileRows = 0;//合并后的文件的当前记录数量int nMaxFileRows = 0;//合并后的文件的最大记录数量char chFileMask[50] = { 0 };//命令行参数中传进来的输出文件名称的前缀int GetFile(char * src_dir, char *src_file_name);void usage(char *process_name);int DealOneFile(char *srcFileNameWithPath, char*bakFileNameWithPath,char * destFilePath, char * destFileName);int GetMMHHSS(char * mmhhss);int GetYYYYMMDD(char * yymmdd);int GetMMDD(char * mmdd);/*程序的参数:process_name sleep_time src_dir src_file_mask src_bak_dir dest_dir desc_file_mask file_rowsprocess_name 程序名字本身sleep_time 程序休眠的时间src_dir 原来的目录路径src_file_mask 原始文件的掩码src_bak_dir 备份文件的路径dest_dir 新的目录路径desc_file_mask 新的文件名称掩码file_rows 合并后的文件达到file_rows的记录后,重新建立一个文件启动方式举例:./mergeCdr 60 /hnibm/henan/mergeCdr A /hnibm/henan/mergeCdr/bak /hnibm/henan/mergeCdr A 3*/int main(int argc, char ** argv){printf("==============process [%s] begin...==============\n", argv[0]);    //参数校验if(argc == 2 &&( strcmp(argv[1],"-v") == 0 || strcmp(argv[1],"-V") == 0 )){printf("current version is [%s]\nbulid time is [%s %s]\n",__VER__, __DATE__,__TIME__);        return 0;}else if( argc != 8){printf("process need 7 parameters!\n");usage(argv[0]);return 2;}sprintf(chFileMask, "%s", argv[6]);nMaxFileRows = atol(argv[7]);    //主要业务的处理while(true){//取得当前的日期和时间,用于生成目标文件名称        char szyyyymmdd[15] = {0};        GetYYYYMMDD(szyyyymmdd);        char szhhmiss[15] = {0};        GetMMHHSS(szhhmiss);        char szmmdd[10] = {0};        GetMMDD(szmmdd);        printf("current date and time is [%s %s]!\n",szyyyymmdd,szhhmiss);        //取得需要处理的文件列表        int ret = GetFile(argv[2],argv[3]);        if(ret != 0)        {            return ret;        }        if(vec_file.size() == 0)        {            printf("no files to be need\n");        }        else        {            printf("there are [%d] files need to deal\n",vec_file.size());            //规整输入的文件名称            char szSrcFilePath[FILE_NAME_LEN] = {0};            if(argv[2][strlen(argv[2])-1] != '/')            {                sprintf(szSrcFilePath,"%s%s",argv[2],"/");            }            printf("src file path is [%s]\n",szSrcFilePath);            //规整备份文件的路径名称            char szBakFilePath[FILE_NAME_LEN] = {0};            if(argv[4][strlen(argv[4])-1] != '/')            {                sprintf(szBakFilePath,"%s%s",argv[4],"/" );            }            printf("backup file path is [%s]\n",szBakFilePath);            //规整输出的路径名称char szDestFilePath[FILE_NAME_LEN] = { 0 };            if(argv[5][strlen(argv[5])-1] != '/')            {                sprintf(szDestFilePath,"%s%s",argv[5],"/" );            }char szDestFileNameTemp[FILE_NAME_LEN / 2] = { 0 };sprintf(szDestFileNameTemp, "%s_0%s%s_%s.r.XswapX", chFileMask, szmmdd, szhhmiss, szyyyymmdd);            char szSrcFileNameWithPath[FILE_NAME_LEN] = {0};            char szBakFileNameWithPath[FILE_NAME_LEN] = {0};            for(vector<string>::iterator itr = vec_file.begin(); itr != vec_file.end(); itr ++)            {                memset(szSrcFileNameWithPath,0x00,FILE_NAME_LEN);                memset(szBakFileNameWithPath,0x00,FILE_NAME_LEN);                sprintf(szSrcFileNameWithPath,"%s%s",szSrcFilePath,itr->c_str());                sprintf(szBakFileNameWithPath,"%s%s",szBakFilePath,itr->c_str());                printf("begin to deal file [%s]\n",szSrcFileNameWithPath);                //处理一个文件//特别需要注意参数 szDescFileNameTemp,当一个合并文件写满时,它的变量值在处理过程中会发生改变。ret = DealOneFile(szSrcFileNameWithPath, szBakFileNameWithPath, szDestFilePath, szDestFileNameTemp);                if(ret)                {                    //return ret;                    continue;                }            }            //将目标文件的名称进行调整            char szCmd[1024] = {0};string strDestFileNameTemp(szDestFileNameTemp);sprintf(szCmd, "mv %s%s %s%s ", szDestFilePath, szDestFileNameTemp, szDestFilePath, strDestFileNameTemp.substr(0, strDestFileNameTemp.rfind(".")).c_str());            printf("final dest file: [%s]\n", szCmd);            system(szCmd);        }        printf("==============sleep(%d)==============\n", atoi(argv[1]));        sleep(atoi(argv[1]));}return 0;}void usage(char *process_name){printf("USAGE:\n");printf("\t[%s -v]\n",process_name);printf("\t[%s -V]\n",process_name);printf("\t[%s sleep_time src_dir src_file_name_mask src_bak_dir dest_dir dest_file_name_mask file_rows]\n",process_name);}int GetFile(char * src_dir, char *src_file_name){    printf("begin to get files in dir [%s], file name like [%s]\n", src_dir, src_file_name );    DIR *dp;    struct dirent *dirp;    if ((dp = opendir(src_dir)) == NULL)    {        printf("can't open [%s]\n", src_dir);        return 3;    }    vec_file.clear();    int iSrcFileNameLen = strlen(src_file_name);    while ((dirp = readdir(dp)) != NULL)    {        if(strcmp(dirp->d_name,".") == 0 || (strcmp(dirp->d_name,"..") == 0))        {            continue;        }        if(strncmp(dirp->d_name,src_file_name,iSrcFileNameLen) != 0)        {            printf("file name is [%s], skip!\n", dirp->d_name);            continue;        }int nFileNameLen = strlen(dirp->d_name);if (! (dirp->d_name[nFileNameLen - 2] == '.' && dirp->d_name[nFileNameLen - 1] == 'r') ){printf("file name is [%s], skip!\n", dirp->d_name);continue;}        vec_file.push_back(dirp->d_name);    }    closedir(dp);    return 0;}int DealOneFile(char *srcFileNameWithPath, char*bakFileNameWithPath, char * destFilePath, char * destFileName){    ifstream src_file(srcFileNameWithPath);char szDestFileNameWithPath[FILE_NAME_LEN] = { 0 };sprintf(szDestFileNameWithPath, "%s%s", destFilePath, destFileName);printf("dest file name with path is [%s]\n", szDestFileNameWithPath);ofstream dest_file(szDestFileNameWithPath, ofstream::app);    if(!src_file.is_open())    {        printf("open src file [%s] Error\n",srcFileNameWithPath);        return 4;    }    if(!dest_file.is_open())    {printf("open dest file [%s] Error\n", szDestFileNameWithPath);        return 5;    }    char szBuffer[BUFFER_LEN] = {0};    //复制文件    while (! src_file.eof() )    {        memset(szBuffer,0x00,BUFFER_LEN);        /*//read 函数是读取一块数据,会有多行,不能使用此函数        src_file.read(szBuffer,BUFFER_LEN);        dest_file << szBuffer;        */        src_file.getline(szBuffer,BUFFER_LEN);        if(strlen(szBuffer) == 0)        {            printf("empty line, skip\n" );            continue;        }        dest_file << szBuffer <<endl;        nFileRows ++;        //如果一个文件“被写满”,写下一个文件        if( nFileRows == nMaxFileRows)        {            printf("file is full, use next file\n");            nFileRows = 0;dest_file.close();//将目标文件的名称进行调整string strDestFileName(destFileName);char szCmd[1024] = { 0 };sprintf(szCmd, "mv %s %s%s", szDestFileNameWithPath, destFilePath, strDestFileName.substr(0, strDestFileName.rfind(".")).c_str());printf("final dest file: [%s]\n", szCmd);system(szCmd);//为了防止新的目标文件名与上一次产生的文件名重复sleep(1);char szyyyymmdd[15] = { 0 };GetYYYYMMDD(szyyyymmdd);char szhhmiss[15] = { 0 };GetMMHHSS(szhhmiss);char szmmdd[10] = { 0 };GetMMDD(szmmdd);//此处需要修改函数的入参,好让此文件名供后续的其他需要处理的源文件使用。sprintf(destFileName, "%s_0%s%s_%s.r.XswapX", chFileMask, szmmdd, szhhmiss, szyyyymmdd);sprintf(szDestFileNameWithPath, "%s%s", destFilePath, destFileName);printf("new dest file name with path is [%s]\n", szDestFileNameWithPath);dest_file.open(szDestFileNameWithPath, ofstream::app);        }    }    //dest_file<<endl;    dest_file.close();    src_file.close();    //将原始文件进行备份    char szCmd[1024] = {0};    sprintf(szCmd,"mv %s %s",srcFileNameWithPath,bakFileNameWithPath );    printf("backup file: [%s]\n", szCmd);    system(szCmd);    return 0;}int GetMMHHSS(char * mmhhss){    time_t current_time = time(0);    struct tm *mStLocalTime = localtime(¤t_time);    sprintf(mmhhss,"%02d%02d%02d",mStLocalTime->tm_hour,mStLocalTime->tm_min,mStLocalTime->tm_sec);    return 0;}int GetYYYYMMDD(char * yymmdd){    time_t current_time = time(0);    struct tm *mStLocalTime = localtime(¤t_time);    sprintf(yymmdd,"%04d%02d%02d",mStLocalTime->tm_year+1900,mStLocalTime->tm_mon + 1,mStLocalTime->tm_mday);    return 0;}int GetMMDD(char * mmdd){    time_t current_time = time(0);    struct tm *mStLocalTime = localtime(¤t_time);    sprintf(mmdd,"%02d%02d",mStLocalTime->tm_mon + 1,mStLocalTime->tm_mday);    return 0;}

测试命令

测试命令:./mergeCdr 60 /hnibm/henan/mergeCdr A /hnibm/henan/mergeCdr/bak /hnibm/henan/mergeCdr A 1000
命令说明
./mergeCdr 程序本身的名称;
60 程序循环变量指定的原始文件目录时,所休眠的时间,以秒为单位;
/hnibm/henan/mergeCdr 程序需要处理的原始文件目录;
A 程序需要处理的原始文件目录中的以字符'A' 开头的文件名称;
/hnibm/henan/mergeCdr/bak 程序需要处理的原始文件在处理后的备份的路径;
/hnibm/henan/mergeCdr 程序需要存放的合并后的文件的路径;
A 合并后的文件的名称前缀,最终的文件名为“A_0mmddhhmiss_yyyymmdd.r”;
1000 合并后的文件的记录数量的最大值,当文件的记录数量达到此值后,系统会创建一个新的记录文件;


备注:
我测试的时候,原始文件的路径和合并后的文件存放的路径是一致的,原始文件的名称匹配字符和合并后的文件的名称前缀也是一致的,这种源和目的都一样的情况,会导致数据文件在下一个循环中进行重复处理,虽然不会导致话单错误,但是也是多此一举。所以,在实际生产中,不建议用这种方式进行配置。


原创粉丝点击