即Test_1.txt和Test_2.txt兩個檔案中五條記錄的開始時間的最小值為“20151101 110909”,結束時間的最大值為“20160109 091545”,目前共處理了5條記錄。也就是說,控制檔案的格式為:呼叫起始時間最小值|呼叫結束時間最大值|記錄總條數|。
/*********************************************************************** 著作權 (C)2015, Zhou Zhaoxiong。** 檔案名稱:CtlFileCreate.c* 檔案標識:無* 內容摘要:目錄中檔案的讀取及控制檔案的產生* 其它說明:無* 目前的版本:V1.0* 完成日期:20151102***********************************************************************/#include "CtlFileCreate.h"// 全域變數UINT8 g_szSourceDir[500] = {0}; // 需掃描的來源目錄UINT8 g_szCtlFileDir[500] = {0}; // 產生的控制檔案的存放目錄UINT8 g_szSourceBakDir[500] = {0}; // 處理之後的源檔案的備份目錄UINT8 g_szCtlFileName[256] = {0}; // 控制檔案全路徑名UINT8 g_szDataStartTime[50] = {0}; // 所有源檔案中資料記錄的最早開始時間UINT8 g_szDataEndTime[50] = {0}; // 所有源檔案中資料記錄的最晚結束時間UINT32 g_iRecordsSum = 0; // 已處理的記錄的總條數/*********************************************************************** 功能描述: 讀取控制檔案中的開始時間、結束時間和記錄條數* 輸入參數: 無* 輸出參數: 無* 返 回 值: 無* 其它說明: 無* 修改日期 版本號碼 修改人 修改內容* ------------------------------------------------------------------* 20151102 V1.0 Zhou Zhaoxiong 建立********************************************************************/void ReadCtlFile(void){ UINT8 *pszHomePath = NULL; FILE *fpCtlFile = NULL; UINT8 szBuf[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: exec GetValueFromStr to get g_szDataStartTime failed!\n"); return; } // 擷取結束時間g_szDataEndTime if (TRUE != GetValueFromStr(2, MML_STR_TYPE, szBuf, g_szDataEndTime, '|', sizeof(g_szDataEndTime))) { printf("ReadCtlFile: exec GetValueFromStr to get g_szDataEndTime failed!\n"); return; } // 擷取記錄條數g_iRecordsSum if (TRUE != GetValueFromStr(3, MML_INT32_TYPE, szBuf, (UINT8 *)&g_iRecordsSum, '|', sizeof(g_iRecordsSum))) { printf("ReadCtlFile: exec GetValueFromStr to get g_iRecordsSum failed!\n"); return; } fclose(fpCtlFile); fpCtlFile = NULL; printf("ReadCtlFile: DataStartTime=%s, DataEndTime=%s, RecordsSum=%d\n", g_szDataStartTime, g_szDataEndTime, g_iRecordsSum); }}/*********************************************************************** 功能描述: 掃描源檔案目錄, 並寫控制檔案* 輸入參數: 無* 輸出參數: 無* 返 回 值: 無* 其它說明: 無* 修改日期 版本號碼 修改人 修改內容* ------------------------------------------------------------------* 20151102 V1.0 Zhou Zhaoxiong 建立********************************************************************/void ReadSrcFileAndWriteCtlFile(void){ UINT8 *pszHomePath = NULL; UINT8 szCommandBuf[500] = {0}; UINT8 szSrcFile[500] = {0}; DIR *pDir = NULL; struct dirent *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: pDir is NULL!\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 %s to %s\n", pDirent->d_name, g_szSourceBakDir); } } closedir(pDir); pDir = NULL; Sleep(60 * 1000); // 每1分鐘掃描一次 }}/*********************************************************************** 功能描述: 擷取源檔案中的內容, 並寫控制檔案* 輸入參數: pszSrcFileName-帶路徑的源檔案名稱* 輸出參數: 無* 返 回 值: 無* 其它說明: 無* 修改日期 版本號碼 修改人 修改內容* ------------------------------------------------------------------* 20151102 V1.0 Zhou Zhaoxiong 建立********************************************************************/void GetSrcFileContentAndWriteCtlFile(UINT8 *pszSrcFileName){ FILE *fp = NULL; UINT8 szContentLine[1024] = {0}; T_SrcFileContent tSrcFileContent = {0}; if (pszSrcFileName == NULL) { printf("GetSrcFileContentAndWriteCtlFile: pDir is NULL!\n"); return; } if ((fp = fopen(pszSrcFileName, "r")) == NULL) // 唯讀方式開啟 { printf("GetSrcFileContentAndWriteCtlFile: open src file failed!\n"); return; } else { while (feof(fp) == 0 && ferror(fp) == 0) { // 每行對應一條源檔案記錄 memset(szContentLine, 0x00, sizeof(szContentLine)); if (fgets(szContentLine, sizeof(szContentLine), fp) == NULL) { printf("GetSrcFileContentAndWriteCtlFile: exec fgets to get line null.\n"); } else { printf("GetSrcFileContentAndWriteCtlFile: get content line: %s\n", szContentLine); } RemoveLineEnd(szContentLine); // 去掉字串後面的斷行符號分行符號 if (strlen(szContentLine) == 0) // 如果為空白行, 則繼續處理下一條 { printf("GetSrcFileContentAndWriteCtlFile: the length of ContentLine is 0, 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|* 修改日期 版本號碼 修改人 修改內容* ------------------------------------------------------------------* 20151102 V1.0 Zhou Zhaoxiong 建立********************************************************************/void GetCtlFileContentAndWrite(T_SrcFileContent *ptSrcFileContent, UINT8 *pszContentBuffer){ UINT8 szContentLine[500] = {0}; if (ptSrcFileContent == NULL || pszContentBuffer == NULL) { printf("GetCtlFileContentAndWrite: ptSrcFileContent or pszContentBuffer is NULL!\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: DataStartTime is %s, DataEndTime is %s, RecordsSum is %d\n", g_szDataStartTime, g_szDataEndTime, g_iRecordsSum); // 組裝寫到控制檔案中的訊息內容 snprintf(szContentLine, sizeof(szContentLine)-1, "%s|%s|%d|", g_szDataStartTime, g_szDataEndTime, g_iRecordsSum); printf("GetCtlFileContentAndWrite: ContentLine is %s\n", szContentLine); strncpy(pszContentBuffer, szContentLine, strlen(szContentLine));}/*********************************************************************** 功能描述: 擷取源檔案中的各個欄位的值* 輸入參數: pszContentLine-一條記錄* 輸出參數: ptSrcFileContent-源檔案中一條記錄中各個欄位的值* 返 回 值: 無* 其它說明: 源檔案中每條記錄的格式為: SrcNumber|DstNumber|DataStartTime|DataEndTime|* 修改日期 版本號碼 修改人 修改內容* ------------------------------------------------------------------* 20151102 V1.0 Zhou Zhaoxiong 建立********************************************************************/void GetSrcFileFieldValue(UINT8 *pszContentLine, T_SrcFileContent *ptSrcFileContent){ if (pszContentLine == NULL || ptSrcFileContent == NULL) { printf("GetSrcFileFieldValue: ContentLine or SrcFileContent is NULL!\n"); return; } // 擷取源號碼 if (TRUE != GetValueFromStr(1, MML_STR_TYPE, pszContentLine, ptSrcFileContent->szSrcNumber, '|', sizeof(ptSrcFileContent->szSrcNumber))) { printf("GetSrcFileFieldValue: exec GetValueFromStr to get szSrcNumber failed!\n"); return; } // 擷取目的號碼 if (TRUE != GetValueFromStr(2, MML_STR_TYPE, pszContentLine, ptSrcFileContent->szDstNumber, '|', sizeof(ptSrcFileContent->szDstNumber))) { printf("GetSrcFileFieldValue: exec GetValueFromStr to get szDstNumber failed!\n"); return; } // 擷取開始時間 if (TRUE != GetValueFromStr(3, MML_STR_TYPE, pszContentLine, ptSrcFileContent->szDataStartTime, '|', sizeof(ptSrcFileContent->szDataStartTime))) { printf("GetSrcFileFieldValue: exec GetValueFromStr to get szDataStartTime failed!\n"); return; } // 擷取結束時間 if (TRUE != GetValueFromStr(4, MML_STR_TYPE, pszContentLine, ptSrcFileContent->szDataEndTime, '|', sizeof(ptSrcFileContent->szDataEndTime))) { printf("GetSrcFileFieldValue: exec GetValueFromStr to get szDataEndTime failed!\n"); return; } printf("GetSrcFileFieldValue: SrcNumber=%s, DstNumber=%s, DataStartTime=%s, DataEndTime=%s\n", ptSrcFileContent->szSrcNumber, ptSrcFileContent->szDstNumber, ptSrcFileContent->szDataStartTime, ptSrcFileContent->szDataEndTime);}/*********************************************************************** 功能描述: 程式休眠* 輸入參數: iCountMs-休眠時間(單位:ms)* 輸出參數: 無* 返 回 值: 無* 其它說明: 無* 修改日期 版本號碼 修改人 修改內容* ------------------------------------------------------------------* 20151102 V1.0 Zhou Zhaoxiong 建立********************************************************************/void Sleep(UINT32 iCountMs){ struct timeval t_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-失敗*其它說明:無*修改日期 版本號碼 修改人 修改內容* --------------------------------------------------------------* 20151102 V1.0 Zhou Zhaoxiong 建立***********************************************************************/BOOL GetValueFromStr(UINT16 iSerialNum, UINT8 iContentType, UINT8 *pSourceStr, UINT8 *pDstStr, UINT8 cIsolater, UINT32 iDstStrSize){ UINT8 *pStrBegin = NULL; UINT8 *pStrEnd = NULL; UINT8 szRetBuf[MAX_RET_BUF_LEN] = {0}; // 截取出的字串放入該數組中 UINT8 *pUINT8 = NULL; UINT16 *pUINT16 = NULL; UINT32 *pUINT32 = NULL; UINT32 iFieldLen = 0; // 用於表示每個欄位的實際長度 if (pSourceStr == NULL) // 對輸入指標的異常情況進行判斷 { return FALSE; } //欄位首 pStrBegin = pSourceStr; while (--iSerialNum != 0) { pStrBegin = strchr(pStrBegin, cIsolater); if (pStrBegin == NULL) { return FALSE; } pStrBegin ++; } //欄位尾 pStrEnd = strchr(pStrBegin, cIsolater); if (pStrEnd == NULL) { return FALSE; } iFieldLen = (UINT16)(pStrEnd - pStrBegin); if(iFieldLen >= MAX_RET_BUF_LEN) //進行異常保護, 防止每個欄位的值過長 { iFieldLen = MAX_RET_BUF_LEN - 1; } memcpy(szRetBuf, pStrBegin, iFieldLen); //將需要的欄位值放到pDstStr中去 switch (iContentType) { case MML_STR_TYPE: //字串類型 { strncpy(pDstStr, szRetBuf, iDstStrSize); break; } case MML_INT8_TYPE: //字元類型 { pUINT8 = (UINT8 *)pDstStr; *pDstStr = (UINT8)atoi(szRetBuf); break; } case MML_INT16_TYPE: // short int類型 { pUINT16 = (UINT16 *)pDstStr; *pUINT16 = (UINT16)atoi(szRetBuf); break; } case MML_INT32_TYPE: // int類型 { pUINT32 = (UINT32 *)pDstStr; *pUINT32 = (UINT32)atoi(szRetBuf); break; } default: // 一定要有default分支 { return FALSE; } } return TRUE;}/*********************************************************************** 功能描述: 去掉字串後面的斷行符號分行符號* 輸入參數: pszStr-輸入的字串* 輸出參數: 無* 返 回 值: 無* 其它說明: 無* 修改日期 版本號碼 修改人 修改內容* ------------------------------------------------------------------* 20151102 V1.0 Zhou Zhaoxiong 建立********************************************************************/void RemoveLineEnd(UINT8 *pszStr){ UINT32 iStrLen = 0; if (pszStr == NULL) { printf("RemoveLineEnd: pszStr is NULL!\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-一條檔案記錄 * 輸出參數: 無 * 返 回 值: 無 * 其它說明: 無 * 修改日期 版本號碼 修改人 修改內容 * ------------------------------------------------------ * 20151103 V1.0 Zhou Zhaoxiong 建立 ***********************************************************************/void WriteToCtlFile(UINT8 *pszContentLine){ FILE *fpCtlFile = NULL; if (pszContentLine == NULL) { printf("WriteToCtlFile: pszContentLine is NULL.\n"); return; } fpCtlFile = fopen(g_szCtlFileName, "w"); if (fpCtlFile != NULL) { fputs(pszContentLine, fpCtlFile); fclose(fpCtlFile); fpCtlFile = NULL; printf("WriteToCtlFile: write ctl file successfully! file=%s, content=%s\n", g_szCtlFileName, pszContentLine); } else { printf("WriteToCtlFile: write ctl file failed! file=%s, content=%s\n", g_szCtlFileName, pszContentLine); }}
第三,在讀取檔案中的第一條記錄時,將該條記錄中的呼叫起始時間和呼叫結束時間分別存放到兩個全域變數中,並按照格式寫控制檔案;在讀取該檔案中的其他記錄時,首先將該條記錄中的呼叫起始時間和呼叫結束時間與全域變數進行比較,確保全域變數中存放的是呼叫起始時間最小值和呼叫結束時間最大值,記錄總條數加1,並將新的記錄內容寫入到控制檔案中。