分批讀取檔案中資料的程式流程及其C代碼實現,流程代碼
一、概述
在實際的軟體開發項目中,經常需要處理大量的檔案。某些檔案中包含了相當多的資料記錄數,如作者本人蔘與過的項目中,一個檔案中有好幾十萬條記錄。如果一次性將多條記錄讀入,則會花費大量的處理時間,且佔用大量的記憶體。
為此,要求對於包含大量資料記錄的檔案進行分批讀取操作,即每一輪讀取一定數目的資料記錄,待將這些記錄處理完成之後,再讀取下一批資料。本文介紹分批讀取檔案中資料的程式流程,並給出了C程式實現。
二、總體程式流程
實現分批讀取檔案中資料的程式流程1所示。
圖1 實現分批讀取檔案中資料的程式流程
三、C程式實現
本程式命名為BatchReadFile.c,具體代碼如下:
/*********************************************************************** 著作權 (C)2015, Zhou Zhaoxiong。** 檔案名稱:BatchReadFile.c* 檔案標識:無* 內容摘要:分批讀取檔案中的資料並列印出來* 其它說明:無* 目前的版本:V1.0* 作 者:Zhou Zhaoxiong* 完成日期:20150528***********************************************************************/#include <stdio.h>// 重定義資料類型typedef signed int INT32;typedef unsigned int UINT32;typedef unsigned char UINT8;// 宏定義#define ONCE_READ_COUNT 5 // 一次讀取的最大資料條數#define MAX_RECORD_LEN 50 // 每條資料的最大長度// 函式宣告INT32 ReadRecordFromFile(FILE *fp, UINT8 szRecordSet[][MAX_RECORD_LEN], UINT32 *piReadCnt);INT32 main();/*********************************************************************** 功能描述:主函數* 輸入參數:無* 輸出參數:無* 返 回 值:無* 其它說明:無* 修改日期 版本號碼 修改人 修改內容* -------------------------------------------------------------------* 20150528 V1.0 Zhou Zhaoxiong 建立***********************************************************************/INT32 main(){ UINT8 szFileName[256] = {0}; // 包含完整路徑的檔案名稱 FILE *fp = NULL; // 檔案控制代碼 UINT32 iReadCnt = 0; // 一次讀取到的記錄數 UINT32 iRecCnt = 0; // 記錄數, 迴圈變數 UINT32 iReadTimes = 0; // 讀取檔案次數 INT32 iRetVal = 0; // 讀取檔案函數的傳回值 UINT8 szRecordSet[ONCE_READ_COUNT][MAX_RECORD_LEN] = {0}; // 存放從檔案中讀取到的記錄內容集 UINT8 szRecordInfo[MAX_RECORD_LEN] = {0}; // 存放從檔案中讀取到的每條記錄內容 // 擷取包含完整路徑的檔案名稱 strcpy(szFileName, "/home/zxin10/zhouzx/test/file/TestFile.txt"); // 開啟檔案 fp = fopen(szFileName, "r"); if (NULL == fp) // 開啟失敗 { printf("Open file %s failed!\n", szFileName); return -1; } // 讀取檔案內容並列印出來 while (1) { iReadCnt = 0; memset(szRecordSet, 0x00, sizeof(szRecordSet)); iRetVal = ReadRecordFromFile(fp, szRecordSet, &iReadCnt); if (iRetVal == -1) // 表示函數執行失敗, 直接退出 { printf("Exec ReadRecordFromFile failed, please check!\n"); break; } if (iReadCnt > 0) { iReadTimes ++; // 讀取次數加1 printf("ReadTimes is: %d, the RecordInfo is:\n", iReadTimes); } for (iRecCnt = 0; iRecCnt < iReadCnt; iRecCnt ++) // 列印讀取到的記錄值 { memset(szRecordInfo, 0x00, sizeof(szRecordInfo)); strncpy(szRecordInfo, szRecordSet[iRecCnt], sizeof(szRecordInfo)-1); printf("%s\n", szRecordInfo); } if (iRetVal == 0) // 表示檔案記錄已掃描完, 直接退出 { break; } } return 0; }/*********************************************************************** 功能描述:從檔案中讀取記錄內容* 輸入參數:fp-檔案指標 * 輸出參數:szRecordSet-記錄內容資訊集 piReadCnt-讀取到的條數* 返 回 值:1-下一輪繼續讀取 0-本輪已讀取完畢 -1-讀取失敗* 其它說明:無* 修改日期 版本號碼 修改人 修改內容* -------------------------------------------------------------------* 20150528 V1.0 Zhou Zhaoxiong 建立***********************************************************************/INT32 ReadRecordFromFile(FILE *fp, UINT8 szRecordSet[][MAX_RECORD_LEN], UINT32 *piReadCnt){ UINT8 szRecordInfo[MAX_RECORD_LEN] = {0}; // 儲存讀取到的每條記錄資訊 UINT32 iRecordLen = 0; // 儲存讀取到的每條記錄資訊的長度 if (fp == NULL || piReadCnt == NULL) { printf("ReadRecordFromFile: input paramter(s) is NULL!\n"); return -1; } // 讀取檔案記錄 while ((!feof(fp)) && (!ferror(fp))) // 遇到檔案結尾或讀取錯誤則退出 { // 讀取一條記錄 memset(szRecordInfo, 0x00, sizeof(szRecordInfo)); fgets(szRecordInfo, sizeof(szRecordInfo)-1, fp); // 去掉記錄後面的斷行符號分行符號 iRecordLen = strlen(szRecordInfo); while (iRecordLen > 0) { if (szRecordInfo[iRecordLen-1] == '\n' || szRecordInfo[iRecordLen-1] == '\r') { szRecordInfo[iRecordLen-1] = '\0'; } else { break; } iRecordLen --; } // 判斷是否為空白行, 是則繼續讀取 if (strlen(szRecordInfo) == 0) { continue; } // 將記錄資訊拷貝到輸出緩衝中 strncpy(szRecordSet[(*piReadCnt)++], szRecordInfo, MAX_RECORD_LEN-1); // 如果超出最大條數限制, 則直接返回 if ((*piReadCnt) >= ONCE_READ_COUNT) { return 1; } } return 0;}
四、程式說明
1.被讀取的檔案命名為“TestFile.txt”,存放在“/home/zhou/zhouzx/test/file/”目錄下。
2.為了方便看到效果,程式中設定每一次最大讀取條數為5,每條記錄的最大長度為50(最大長度值的設定的依據是讀取的檔案記錄的長度)。將讀取到的記錄存放到一個二維陣列變數中,其中第一維是每次讀取到的記錄條數,第二維是每條記錄的長度。
3.如果一輪未讀完資料,則檔案指標會自動跳到下一次讀取的記錄的開頭。結束一輪讀取的條件有三個:已達讀取上限、記錄已全部讀完、讀取錯誤。
4.如果檔案中出現了空行,那麼程式並不會將之作為有效行而使得讀取條數增加,而是從下一個非空行開始繼續計數。
5.程式會列印出讀取的次數及每次讀取到的具體記錄資訊,方便查看程式分批處理的執行情況。
五、程式編譯及運行結果
在Linux下,使用“gcc -g -o BatchReadFile BatchReadFile.c”命令對程式進行編譯,產生“BatchReadFile”。下面執行“BatchReadFile”命令來對程式進行測試。
1.“TestFile.txt”檔案中的內容如下:
100001100002100003100004
則程式運行結果為:
ReadTimes is: 1, the RecordInfo is:100001100002100003100004
2.“TestFile.txt”檔案中的內容如下:
100001100002100003100004100005
則程式運行結果為:
ReadTimes is: 1, the RecordInfo is:100001100002100003100004100005
3.“TestFile.txt”檔案中的內容如下:
100001100002100003100004100005100006
則程式運行結果為:
ReadTimes is: 1, the RecordInfo is:100001100002100003100004100005ReadTimes is: 2, the RecordInfo is:100006
4.“TestFile.txt”檔案中的內容如下:
100001100002100003100004100005100006100007100008100009100010100011
則程式運行結果為:
ReadTimes is: 1, the RecordInfo is:100001100002100003100004100005ReadTimes is: 2, the RecordInfo is:100006100007100008100009100010ReadTimes is: 3, the RecordInfo is:100011
可見,即使檔案中存在空行,程式也能夠正常處理。
六、總結
本文對分批讀取檔案中資料的程式流程進行了介紹,並給出了C程式實現。在實際的軟體開發項目中,每個檔案包含的記錄條數要多很多,但基本的程式編寫流程是一樣的。大家可以根據實際需要對本文中的程式進行修改來滿足具體的要求。
本人公眾號:zhouzxi,請掃描以下二維碼: