Linux下控制(统计)文件的生成的C代码实现
本文分享了Linux下控制(统计)文件的生成的C代码实现案例,供大家参考,具体内容如下
一、需求描述
不定时地在Linux机器下的某目录中放入文件,文件内容中包含了用户号码、起止时间等字段,现要求编写一程序来统计目前该目录中所有文件中的记录总条数及所有记录中的最早起始时间和最晚结束时间。
例如,该目录中有两个文件Test_1.txt和Test_2.txt,其中Test_1.txt文件内容为:
- 15696192591|15696192592|20151103120909|20151103201545|
- 15696192593|15696192594|20151103110909|20151103191545|
- 02344273522|02344273523|20160108110909|20160109091545|
Test_2.txt文件内容为:
- 15696192595|15696192596|20151102120909|20151104201545|
- 15696192597|15696192598|20151101110909|20151103191545|
即文件中的每条记录的格式为:呼叫号码|被呼叫号码|呼叫起始时间|呼叫结束时间|,要求生成的控制文件CtlFile.txt的内容为:
- 20151101110909|20160109091545|5|
即Test_1.txt和Test_2.txt两个文件中五条记录的开始时间的最小值为“20151101110909”,结束时间的最大值为“20160109091545”,目前共处理了5条记录。也就是说,控制文件的格式为:呼叫起始时间最小值|呼叫结束时间最大值|记录总条数|。
二、程序代码
本程序一共包括了三个代码文件:main.c、CtlFileCreate.c和CtlFileCreate.h,具体代码如下:
main.c
/********************************************************************** *版权所有(C)2016,ZhouZhaoxiong。 * *文件名称:CtlFileCreate.c *文件标识:无 *内容摘要:目录中文件的读取及控制文件的生成 *其它说明:无 *当前版本:V1.0 *完成日期:20160109 * **********************************************************************/ #include"CtlFileCreate.h" /********************************************************************** *功能描述:主函数 *输入参数:无 *输出参数:无 *返回值:无 *其它说明:无 *修改日期版本号修改人修改内容 *------------------------------------------------------------------- *20160109V1.0ZhouZhaoxiong创建 ***********************************************************************/ INT32main() { ReadCtlFile();//获取控制文件存放路径、控制文件全路径名及文件内容字段值 ReadSrcFileAndWriteCtlFile();//扫描源文件目录,并写控制文件 return0; }
CtlFileCreate.h
/********************************************************************** *版权所有(C)2015,ZhouZhaoxiong。 * *文件名称:CtlFileCreate.h *文件标识:无 *内容摘要:目录中文件的读取及控制文件的生成 *其它说明:无 *当前版本:V1.0 *完成日期:20151102 * **********************************************************************/ #include<stdio.h> #include<stdlib.h> #include<string.h> #include<dirent.h> //数据类型重定义 typedefunsignedcharUINT8; typedefunsignedshortintUINT16; typedefunsignedintUINT32; typedefsignedintINT32; typedefunsignedcharBOOL; //参数类型 #defineMML_INT8_TYPE0 #defineMML_INT16_TYPE1 #defineMML_INT32_TYPE2 #defineMML_STR_TYPE3 #defineTRUE(BOOL)1 #defineFALSE(BOOL)0 //字段最大长度 #defineMAX_RET_BUF_LEN1024 //源文件字段结构体 typedefstruct { UINT8szSrcNumber[50]; UINT8szDstNumber[50]; UINT8szDataStartTime[50]; UINT8szDataEndTime[50]; }T_SrcFileContent; //函数声明 voidSleep(UINT32iCountMs); voidReadCtlFile(void); voidReadSrcFileAndWriteCtlFile(void); voidGetSrcFileContentAndWriteCtlFile(UINT8*pszSrcFileName); voidGetSrcFileFieldValue(UINT8*pszContentLine,T_SrcFileContent*ptSrcFileContent); voidGetCtlFileContentAndWrite(T_SrcFileContent*ptSrcFileContent,UINT8*pszContentBuffer); BOOLGetValueFromStr(UINT16iSerialNum,UINT8iContentType,UINT8*pSourceStr,UINT8*pDstStr,UINT8cIsolater,UINT32iDstStrSize); voidRemoveLineEnd(UINT8*pszStr); voidWriteToCtlFile(UINT8*pszContentLine);
CtlFileCreate.c
/********************************************************************** *版权所有(C)2015,ZhouZhaoxiong。 * *文件名称:CtlFileCreate.c *文件标识:无 *内容摘要:目录中文件的读取及控制文件的生成 *其它说明:无 *当前版本:V1.0 *完成日期:20151102 * **********************************************************************/ #include"CtlFileCreate.h" //全局变量 UINT8g_szSourceDir[500]={0};//需扫描的源目录 UINT8g_szCtlFileDir[500]={0};//生成的控制文件的存放目录 UINT8g_szSourceBakDir[500]={0};//处理之后的源文件的备份目录 UINT8g_szCtlFileName[256]={0};//控制文件全路径名 UINT8g_szDataStartTime[50]={0};//所有源文件中数据记录的最早开始时间 UINT8g_szDataEndTime[50]={0};//所有源文件中数据记录的最晚结束时间 UINT32g_iRecordsSum=0;//已处理的记录的总条数 /********************************************************************** *功能描述:读取控制文件中的开始时间、结束时间和记录条数 *输入参数:无 *输出参数:无 *返回值:无 *其它说明:无 *修改日期版本号修改人修改内容 *------------------------------------------------------------------ *20151102V1.0ZhouZhaoxiong创建 ********************************************************************/ voidReadCtlFile(void) { UINT8*pszHomePath=NULL; FILE*fpCtlFile=NULL; UINT8szBuf[500]={0}; //读取控制文件中的开始时间、结束时间和记录条数,如果是当天程序重启,则记录条数继续编号 pszHomePath=getenv("HOME"); if(pszHomePath==NULL) { return; } snprintf(g_szCtlFileDir,sizeof(g_szCtlFileDir)-1,"%s/zhouzhaoxiong/zzx/CtlFileCreate/CtlFile",pszHomePath);//控制文件存放目录 snprintf(g_szCtlFileName,sizeof(g_szCtlFileName)-1,"%s/CtlFile.txt",g_szCtlFileDir);//控制文件全路径名 fpCtlFile=fopen(g_szCtlFileName,"r"); if(fpCtlFile!=NULL) { fgets(szBuf,sizeof(szBuf),fpCtlFile); //获取开始时间g_szDataStartTime if(TRUE!=GetValueFromStr(1,MML_STR_TYPE,szBuf,g_szDataStartTime,'|',sizeof(g_szDataStartTime))) { printf("ReadCtlFile:execGetValueFromStrtogetg_szDataStartTimefailed!\n"); return; } //获取结束时间g_szDataEndTime if(TRUE!=GetValueFromStr(2,MML_STR_TYPE,szBuf,g_szDataEndTime,'|',sizeof(g_szDataEndTime))) { printf("ReadCtlFile:execGetValueFromStrtogetg_szDataEndTimefailed!\n"); return; } //获取记录条数g_iRecordsSum if(TRUE!=GetValueFromStr(3,MML_INT32_TYPE,szBuf,(UINT8*)&g_iRecordsSum,'|',sizeof(g_iRecordsSum))) { printf("ReadCtlFile:execGetValueFromStrtogetg_iRecordsSumfailed!\n"); return; } fclose(fpCtlFile); fpCtlFile=NULL; printf("ReadCtlFile:DataStartTime=%s,DataEndTime=%s,RecordsSum=%d\n",g_szDataStartTime,g_szDataEndTime,g_iRecordsSum); } } /********************************************************************** *功能描述:扫描源文件目录,并写控制文件 *输入参数:无 *输出参数:无 *返回值:无 *其它说明:无 *修改日期版本号修改人修改内容 *------------------------------------------------------------------ *20151102V1.0ZhouZhaoxiong创建 ********************************************************************/ voidReadSrcFileAndWriteCtlFile(void) { UINT8*pszHomePath=NULL; UINT8szCommandBuf[500]={0}; UINT8szSrcFile[500]={0}; DIR*pDir=NULL; structdirent*pDirent=NULL; pszHomePath=getenv("HOME"); if(pszHomePath==NULL) { return; } snprintf(g_szSourceDir,sizeof(g_szSourceDir)-1,"%s/zhouzhaoxiong/zzx/CtlFileCreate/SrcFile",pszHomePath);//源文件存放目录 snprintf(g_szSourceBakDir,sizeof(g_szSourceBakDir)-1,"%s/zhouzhaoxiong/zzx/CtlFileCreate/SrcFile_bak",pszHomePath);//源文件备份目录 while(1) { pDir=opendir(g_szSourceDir); if(NULL==pDir) { printf("ReadSrcFileAndWriteCtlFile:pDirisNULL!\n"); continue; } while((pDirent=readdir(pDir))!=NULL)//扫描源目录,获取文件名 { if(strncmp(pDirent->d_name,"Test_",strlen("Test_"))==0)//如果匹配上了源文件的前缀,则读取文件内容并写控制文件 { memset(szSrcFile,0x00,sizeof(szSrcFile)); snprintf(szSrcFile,sizeof(szSrcFile)-1,"%s/%s",g_szSourceDir,pDirent->d_name,g_szSourceBakDir); GetSrcFileContentAndWriteCtlFile(szSrcFile);//获取源文件中的内容,并写控制文件 //处理完成之后,将文件剪切到备份目录中 memset(szCommandBuf,0x00,sizeof(szCommandBuf)); snprintf(szCommandBuf,sizeof(szCommandBuf)-1,"mv%s%s",szSrcFile,g_szSourceBakDir); system(szCommandBuf); printf("ReadSrcFileAndWriteCtlFile:now,move%sto%s\n",pDirent->d_name,g_szSourceBakDir); } } closedir(pDir); pDir=NULL; Sleep(60*1000);//每1分钟扫描一次 } } /********************************************************************** *功能描述:获取源文件中的内容,并写控制文件 *输入参数:pszSrcFileName-带路径的源文件名 *输出参数:无 *返回值:无 *其它说明:无 *修改日期版本号修改人修改内容 *------------------------------------------------------------------ *20151102V1.0ZhouZhaoxiong创建 ********************************************************************/ voidGetSrcFileContentAndWriteCtlFile(UINT8*pszSrcFileName) { FILE*fp=NULL; UINT8szContentLine[1024]={0}; T_SrcFileContenttSrcFileContent={0}; if(pszSrcFileName==NULL) { printf("GetSrcFileContentAndWriteCtlFile:pDirisNULL!\n"); return; } if((fp=fopen(pszSrcFileName,"r"))==NULL)//只读方式打开 { printf("GetSrcFileContentAndWriteCtlFile:opensrcfilefailed!\n"); return; } else { while(feof(fp)==0&&ferror(fp)==0) { //每行对应一条源文件记录 memset(szContentLine,0x00,sizeof(szContentLine)); if(fgets(szContentLine,sizeof(szContentLine),fp)==NULL) { printf("GetSrcFileContentAndWriteCtlFile:execfgetstogetlinenull.\n"); } else { printf("GetSrcFileContentAndWriteCtlFile:getcontentline:%s\n",szContentLine); } RemoveLineEnd(szContentLine);//去掉字符串后面的回车换行符 if(strlen(szContentLine)==0)//如果为空行,则继续处理下一条 { printf("GetSrcFileContentAndWriteCtlFile:thelengthofContentLineis0,continue.\n"); continue; } GetSrcFileFieldValue(szContentLine,&tSrcFileContent);//获取一条记录中各个字段的值 memset(szContentLine,0x00,sizeof(szContentLine)); GetCtlFileContentAndWrite(&tSrcFileContent,szContentLine);//组装写入控制文件中的内容 WriteToCtlFile(szContentLine);//将内容写到控制文件中 } fclose(fp); fp=NULL; } } /********************************************************************** *功能描述:组装写入控制文件中的内容 *输入参数:ptSrcFileContent-源文件中一条记录中各个字段的值 *输出参数:pszContentBuffer-存放内容的缓存 *返回值:无 *其它说明:控制文件中记录为:DataStartTime|DataEndTime|RecordsSum| *修改日期版本号修改人修改内容 *------------------------------------------------------------------ *20151102V1.0ZhouZhaoxiong创建 ********************************************************************/ voidGetCtlFileContentAndWrite(T_SrcFileContent*ptSrcFileContent,UINT8*pszContentBuffer) { UINT8szContentLine[500]={0}; if(ptSrcFileContent==NULL||pszContentBuffer==NULL) { printf("GetCtlFileContentAndWrite:ptSrcFileContentorpszContentBufferisNULL!\n"); return; } //根据值的大小对g_szDataStartTime进行赋值 if(strlen(g_szDataStartTime)==0)//当天第一条 { strncpy(g_szDataStartTime,ptSrcFileContent->szDataStartTime,strlen(ptSrcFileContent->szDataStartTime)); } else { if(strncmp(g_szDataStartTime,ptSrcFileContent->szDataStartTime,strlen(ptSrcFileContent->szDataStartTime))>0)//修改成最小时间 { memset(g_szDataStartTime,0x00,sizeof(g_szDataStartTime)); strncpy(g_szDataStartTime,ptSrcFileContent->szDataStartTime,strlen(ptSrcFileContent->szDataStartTime)); } } //根据值的大小对g_szDataEndTime进行赋值 if(strlen(g_szDataEndTime)==0)//当天第一条 { strncpy(g_szDataEndTime,ptSrcFileContent->szDataEndTime,strlen(ptSrcFileContent->szDataEndTime)); } else { if(strncmp(g_szDataEndTime,ptSrcFileContent->szDataEndTime,strlen(ptSrcFileContent->szDataEndTime))<0)//修改成最大时间 { memset(g_szDataEndTime,0x00,sizeof(g_szDataEndTime)); strncpy(g_szDataEndTime,ptSrcFileContent->szDataEndTime,strlen(ptSrcFileContent->szDataEndTime)); } } //记录总条数加1 g_iRecordsSum=g_iRecordsSum+1;//当天所有记录的总条数加1 //打印三个字段的内容 printf("GetCtlFileContentAndWrite:DataStartTimeis%s,DataEndTimeis%s,RecordsSumis%d\n",g_szDataStartTime,g_szDataEndTime,g_iRecordsSum); //组装写到控制文件中的消息内容 snprintf(szContentLine,sizeof(szContentLine)-1,"%s|%s|%d|",g_szDataStartTime,g_szDataEndTime,g_iRecordsSum); printf("GetCtlFileContentAndWrite:ContentLineis%s\n",szContentLine); strncpy(pszContentBuffer,szContentLine,strlen(szContentLine)); } /********************************************************************** *功能描述:获取源文件中的各个字段的值 *输入参数:pszContentLine-一条记录 *输出参数:ptSrcFileContent-源文件中一条记录中各个字段的值 *返回值:无 *其它说明:源文件中每条记录的格式为:SrcNumber|DstNumber|DataStartTime|DataEndTime| *修改日期版本号修改人修改内容 *------------------------------------------------------------------ *20151102V1.0ZhouZhaoxiong创建 ********************************************************************/ voidGetSrcFileFieldValue(UINT8*pszContentLine,T_SrcFileContent*ptSrcFileContent) { if(pszContentLine==NULL||ptSrcFileContent==NULL) { printf("GetSrcFileFieldValue:ContentLineorSrcFileContentisNULL!\n"); return; } //获取源号码 if(TRUE!=GetValueFromStr(1,MML_STR_TYPE,pszContentLine,ptSrcFileContent->szSrcNumber,'|',sizeof(ptSrcFileContent->szSrcNumber))) { printf("GetSrcFileFieldValue:execGetValueFromStrtogetszSrcNumberfailed!\n"); return; } //获取目的号码 if(TRUE!=GetValueFromStr(2,MML_STR_TYPE,pszContentLine,ptSrcFileContent->szDstNumber,'|',sizeof(ptSrcFileContent->szDstNumber))) { printf("GetSrcFileFieldValue:execGetValueFromStrtogetszDstNumberfailed!\n"); return; } //获取开始时间 if(TRUE!=GetValueFromStr(3,MML_STR_TYPE,pszContentLine,ptSrcFileContent->szDataStartTime,'|',sizeof(ptSrcFileContent->szDataStartTime))) { printf("GetSrcFileFieldValue:execGetValueFromStrtogetszDataStartTimefailed!\n"); return; } //获取结束时间 if(TRUE!=GetValueFromStr(4,MML_STR_TYPE,pszContentLine,ptSrcFileContent->szDataEndTime,'|',sizeof(ptSrcFileContent->szDataEndTime))) { printf("GetSrcFileFieldValue:execGetValueFromStrtogetszDataEndTimefailed!\n"); return; } printf("GetSrcFileFieldValue:SrcNumber=%s,DstNumber=%s,DataStartTime=%s,DataEndTime=%s\n",ptSrcFileContent->szSrcNumber,ptSrcFileContent->szDstNumber, ptSrcFileContent->szDataStartTime,ptSrcFileContent->szDataEndTime); } /********************************************************************** *功能描述:程序休眠 *输入参数:iCountMs-休眠时间(单位:ms) *输出参数:无 *返回值:无 *其它说明:无 *修改日期版本号修改人修改内容 *------------------------------------------------------------------ *20151102V1.0ZhouZhaoxiong创建 ********************************************************************/ voidSleep(UINT32iCountMs) { structtimevalt_timeout={0}; if(iCountMs<1000) { t_timeout.tv_sec=0; t_timeout.tv_usec=iCountMs*1000; } else { t_timeout.tv_sec=iCountMs/1000; t_timeout.tv_usec=(iCountMs%1000)*1000; } select(0,NULL,NULL,NULL,&t_timeout);//调用select函数阻塞程序 } /********************************************************************** *功能描述:获取字符串中某一个字段的值 *输入参数:iSerialNum-字段编号(为正整数) iContentType-需要获取的内容的类型 pSourceStr-源字符串 pDstStr-目的字符串(提取的值的存放位置) cIsolater-源字符串中字段的分隔符 iDstStrSize-目的字符串的长度 *输出参数:无 *返回值:TRUE-成功FALSE-失败 *其它说明:无 *修改日期版本号修改人修改内容 *-------------------------------------------------------------- *20151102V1.0ZhouZhaoxiong创建 ***********************************************************************/ BOOLGetValueFromStr(UINT16iSerialNum,UINT8iContentType,UINT8*pSourceStr,UINT8*pDstStr,UINT8cIsolater,UINT32iDstStrSize) { UINT8*pStrBegin=NULL; UINT8*pStrEnd=NULL; UINT8szRetBuf[MAX_RET_BUF_LEN]={0};//截取出的字符串放入该数组中 UINT8*pUINT8=NULL; UINT16*pUINT16=NULL; UINT32*pUINT32=NULL; UINT32iFieldLen=0;//用于表示每个字段的实际长度 if(pSourceStr==NULL)//对输入指针的异常情况进行判断 { returnFALSE; } //字段首 pStrBegin=pSourceStr; while(--iSerialNum!=0) { pStrBegin=strchr(pStrBegin,cIsolater); if(pStrBegin==NULL) { returnFALSE; } pStrBegin++; } //字段尾 pStrEnd=strchr(pStrBegin,cIsolater); if(pStrEnd==NULL) { returnFALSE; } iFieldLen=(UINT16)(pStrEnd-pStrBegin); if(iFieldLen>=MAX_RET_BUF_LEN)//进行异常保护,防止每个字段的值过长 { iFieldLen=MAX_RET_BUF_LEN-1; } memcpy(szRetBuf,pStrBegin,iFieldLen); //将需要的字段值放到pDstStr中去 switch(iContentType) { caseMML_STR_TYPE://字符串类型 { strncpy(pDstStr,szRetBuf,iDstStrSize); break; } caseMML_INT8_TYPE://字符类型 { pUINT8=(UINT8*)pDstStr; *pDstStr=(UINT8)atoi(szRetBuf); break; } caseMML_INT16_TYPE://shortint类型 { pUINT16=(UINT16*)pDstStr; *pUINT16=(UINT16)atoi(szRetBuf); break; } caseMML_INT32_TYPE://int类型 { pUINT32=(UINT32*)pDstStr; *pUINT32=(UINT32)atoi(szRetBuf); break; } default://一定要有default分支 { returnFALSE; } } returnTRUE; } /********************************************************************** *功能描述:去掉字符串后面的回车换行符 *输入参数:pszStr-输入的字符串 *输出参数:无 *返回值:无 *其它说明:无 *修改日期版本号修改人修改内容 *------------------------------------------------------------------ *20151102V1.0ZhouZhaoxiong创建 ********************************************************************/ voidRemoveLineEnd(UINT8*pszStr) { UINT32iStrLen=0; if(pszStr==NULL) { printf("RemoveLineEnd:pszStrisNULL!\n"); return; } iStrLen=strlen(pszStr); while(iStrLen>0) { if(pszStr[iStrLen-1]=='\n'||pszStr[iStrLen-1]=='\r') { pszStr[iStrLen-1]='\0'; } else { break; } iStrLen--; } return; } /********************************************************************** *功能描述:把内容写到控制文件中 *输入参数:pszContentLine-一条文件记录 *输出参数:无 *返回值:无 *其它说明:无 *修改日期版本号修改人修改内容 *------------------------------------------------------ *20151103V1.0ZhouZhaoxiong创建 ***********************************************************************/ voidWriteToCtlFile(UINT8*pszContentLine) { FILE*fpCtlFile=NULL; if(pszContentLine==NULL) { printf("WriteToCtlFile:pszContentLineisNULL.\n"); return; } fpCtlFile=fopen(g_szCtlFileName,"w"); if(fpCtlFile!=NULL) { fputs(pszContentLine,fpCtlFile); fclose(fpCtlFile); fpCtlFile=NULL; printf("WriteToCtlFile:writectlfilesuccessfully!file=%s,content=%s\n",g_szCtlFileName,pszContentLine); } else { printf("WriteToCtlFile:writectlfilefailed!file=%s,content=%s\n",g_szCtlFileName,pszContentLine); } }
三、程序编译及运行
将程序代码上传到Linux机器上,并在当前用户的zhouzhaoxiong/zzx/CtlFileCreate/SrcFile目录下上传一些满足命名规范的源文件,然后使用“gcc-g-oCtlFileCreatemain.cCtlFileCreate.c”命令对程序进行编译,生成“CtlFileCreate”文件;接着运行“CtlFileCreate”命令,可以看到在当前用户的zhouzhaoxiong/zzx/CtlFileCreate/CtlFile目录下有控制文件生成,在当前用户的zhouzhaoxiong/zzx/CtlFileCreate/SrcFile_bak目录下有源文件的备份文件生成。
查看控制文件内容,里面记录的就是当前所处理的所有文件中的记录总条数及所有记录中的呼叫起始时间最小值和呼叫结束时间最大值。
四、程序说明
第一,为了便于说明,在本程序中,源文件的前缀是“Test_”,控制文件命名为“CtlFile.txt”。在实际的开发中,大家完全可以通过配置项来决定源文件及控制文件的命名规则。
第二,为了防止源文件被重复处理,当某个源文件处理完成之后,会被剪切到备份目录中。这样做也是为了方便之后校对控制文件中的内容。
第三,在读取文件中的第一条记录时,将该条记录中的呼叫起始时间和呼叫结束时间分别存放到两个全局变量中,并按照格式写控制文件;在读取该文件中的其他记录时,首先将该条记录中的呼叫起始时间和呼叫结束时间与全局变量进行比较,确保全局变量中存放的是呼叫起始时间最小值和呼叫结束时间最大值,记录总条数加1,并将新的记录内容写入到控制文件中。
第四,在处理完当前目录下的所有文件之后,程序会休眠一段时间,然后继续扫描目录。在实际的开发中,休眠间隔也是可以配置的。
以上就是本文的全部内容,希望对大家的学习有所帮助。