分批讀取文件中數(shù)據(jù)的程序流程及其C代碼實現(xiàn)
掃描二維碼
隨時隨地手機看文章
一、概述
在實際的軟件開發(fā)項目中,經(jīng)常需要處理大量的文件。某些文件中包含了相當多的數(shù)據(jù)記錄數(shù),如作者本人參與過的項目中,一個文件中有好幾十萬條記錄。如果一次性將多條記錄讀入,則會花費大量的處理時間,且占用大量的內(nèi)存。為此,要求對于包含大量數(shù)據(jù)記錄的文件進行分批讀取操作,即每一輪讀取一定數(shù)目的數(shù)據(jù)記錄,待將這些記錄處理完成之后,再讀取下一批數(shù)據(jù)。本文介紹分批讀取文件中數(shù)據(jù)的程序流程,并給出了C程序?qū)崿F(xiàn)。
二、總體程序流程
實現(xiàn)分批讀取文件中數(shù)據(jù)的程序流程如圖1所示。
圖1 實現(xiàn)分批讀取文件中數(shù)據(jù)的程序流程
三、C程序?qū)崿F(xiàn)
本程序命名為BatchReadFile.c,具體代碼如下:
/**********************************************************************
* 版權(quán)所有 (C)2015, Zhou Zhaoxiong。
*
* 文件名稱:BatchReadFile.c
* 文件標識:無
* 內(nèi)容摘要:分批讀取文件中的數(shù)據(jù)并打印出來
* 其它說明:無
* 當前版本:V1.0
* 作 者:Zhou Zhaoxiong
* 完成日期:20150528
*
**********************************************************************/
#include <stdio.h>
// 重定義數(shù)據(jù)類型
typedef signed int INT32;
typedef unsigned int UINT32;
typedef unsigned char UINT8;
// 宏定義
#define ONCE_READ_COUNT 5 // 一次讀取的最大數(shù)據(jù)條數(shù)
#define MAX_RECORD_LEN 50 // 每條數(shù)據(jù)的最大長度
// 函數(shù)聲明
INT32 ReadRecordFromFile(FILE *fp, UINT8 szRecordSet[][MAX_RECORD_LEN], UINT32 *piReadCnt);
INT32 main();
/**********************************************************************
* 功能描述:主函數(shù)
* 輸入?yún)?shù):無
* 輸出參數(shù):無
* 返 回 值:無
* 其它說明:無
* 修改日期 版本號 修改人 修改內(nèi)容
* -------------------------------------------------------------------
* 20150528 V1.0 Zhou Zhaoxiong 創(chuàng)建
***********************************************************************/
INT32 main()
{
UINT8 szFileName[256] = {0}; // 包含完整路徑的文件名
FILE *fp = NULL; // 文件句柄
UINT32 iReadCnt = 0; // 一次讀取到的記錄數(shù)
UINT32 iRecCnt = 0; // 記錄數(shù), 循環(huán)變量
UINT32 iReadTimes = 0; // 讀取文件次數(shù)
INT32 iRetVal = 0; // 讀取文件函數(shù)的返回值
UINT8 szRecordSet[ONCE_READ_COUNT][MAX_RECORD_LEN] = {0}; // 存放從文件中讀取到的記錄內(nèi)容集
UINT8 szRecordInfo[MAX_RECORD_LEN] = {0}; // 存放從文件中讀取到的每條記錄內(nèi)容
// 獲取包含完整路徑的文件名
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;
}
// 讀取文件內(nèi)容并打印出來
while (1)
{
iReadCnt = 0;
memset(szRecordSet, 0x00, sizeof(szRecordSet));
iRetVal = ReadRecordFromFile(fp, szRecordSet, &iReadCnt);
if (iRetVal == -1) // 表示函數(shù)執(zhí)行失敗, 直接退出
{
printf("Exec ReadRecordFromFile failed, please check!\n");
break;
}
if (iReadCnt > 0)
{
iReadTimes ++; // 讀取次數(shù)加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;
}
/**********************************************************************
* 功能描述:從文件中讀取記錄內(nèi)容
* 輸入?yún)?shù):fp-文件指針
* 輸出參數(shù):szRecordSet-記錄內(nèi)容信息集
piReadCnt-讀取到的條數(shù)
* 返 回 值:1-下一輪繼續(xù)讀取 0-本輪已讀取完畢 -1-讀取失敗
* 其它說明:無
* 修改日期 版本號 修改人 修改內(nèi)容
* -------------------------------------------------------------------
* 20150528 V1.0 Zhou Zhaoxiong 創(chuàng)建
***********************************************************************/
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))) // 遇到文件結(jié)尾或讀取錯誤則退出
{
// 讀取一條記錄
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 --;
}
// 判斷是否為空行, 是則繼續(xù)讀取
if (strlen(szRecordInfo) == 0)
{
continue;
}
// 將記錄信息拷貝到輸出緩存中
strncpy(szRecordSet[(*piReadCnt)++], szRecordInfo, MAX_RECORD_LEN-1);
// 如果超出最大條數(shù)限制, 則直接返回
if ((*piReadCnt) >= ONCE_READ_COUNT)
{
return 1;
}
}
return 0;
}
四、程序說明
1.被讀取的文件命名為“TestFile.txt”,存放在“/home/zhou/zhouzx/test/file/”目錄下。
2.為了方便看到效果,程序中設(shè)定每一次最大讀取條數(shù)為5,每條記錄的最大長度為50(最大長度值的設(shè)定的依據(jù)是讀取的文件記錄的長度)。將讀取到的記錄存放到一個二維數(shù)組變量中,其中第一維是每次讀取到的記錄條數(shù),第二維是每條記錄的長度。
3.如果一輪未讀完數(shù)據(jù),則文件指針會自動跳到下一次讀取的記錄的開頭。結(jié)束一輪讀取的條件有三個:已達讀取上限、記錄已全部讀完、讀取錯誤。
4.如果文件中出現(xiàn)了空行,那么程序并不會將之作為有效行而使得讀取條數(shù)增加,而是從下一個非空行開始繼續(xù)計數(shù)。
5.程序會打印出讀取的次數(shù)及每次讀取到的具體記錄信息,方便查看程序分批處理的執(zhí)行情況。
五、程序編譯及運行結(jié)果
在Linux下,使用“gcc -g -o BatchReadFile BatchReadFile.c”命令對程序進行編譯,生成“BatchReadFile”。下面執(zhí)行“BatchReadFile”命令來對程序進行測試。
1.“TestFile.txt”文件中的內(nèi)容如下:
100001
100002
100003
100004
則程序運行結(jié)果為:
ReadTimes is: 1, the RecordInfo is:
100001
100002
100003
100004
2.“TestFile.txt”文件中的內(nèi)容如下:
100001
100002
100003
100004
100005
則程序運行結(jié)果為:
ReadTimes is: 1, the RecordInfo is:
100001
100002
100003
100004
100005
3.“TestFile.txt”文件中的內(nèi)容如下:
100001
100002
100003
100004
100005
100006
則程序運行結(jié)果為:
ReadTimes is: 1, the RecordInfo is:
100001
100002
100003
100004
100005
ReadTimes is: 2, the RecordInfo is:
100006
4.“TestFile.txt”文件中的內(nèi)容如下:
100001
100002
100003
100004
100005
100006
100007
100008
100009
100010
100011
則程序運行結(jié)果為:
ReadTimes is: 1, the RecordInfo is:
100001
100002
100003
100004
100005
ReadTimes is: 2, the RecordInfo is:
100006
100007
100008
100009
100010
ReadTimes is: 3, the RecordInfo is:
100011
可見,即使文件中存在空行,程序也能夠正常處理。
六、總結(jié)
本文對分批讀取文件中數(shù)據(jù)的程序流程進行了介紹,并給出了C程序?qū)崿F(xiàn)。在實際的軟件開發(fā)項目中,每個文件包含的記錄條數(shù)要多很多,但基本的程序編寫流程是一樣的。大家可以根據(jù)實際需要對本文中的程序進行修改來滿足具體的要求。
往期精彩
五分鐘讀懂TCP 協(xié)議
為Linux應(yīng)用構(gòu)造有限狀態(tài)機
專為MCU項目開發(fā)提速的代碼框架BabyOS
嵌入式C語言代碼優(yōu)化方案(深度好文,建議花時間研讀并收藏)
stm32cubeMX學(xué)習(xí)、USB DFU(Download Firmware Update)固件更新
若覺得本次分享的文章對您有幫助,隨手點[在看]
并轉(zhuǎn)發(fā)分享,也是對我的支持。
免責聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!