www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 嵌入式云IOT技術(shù)圈
[導(dǎo)讀]一、概述 在實(shí)際的軟件開(kāi)發(fā)項(xiàng)目中,經(jīng)常需要處理大量的文件。某些文件中包含了相當(dāng)多的數(shù)據(jù)記錄數(shù),如作者本人參與過(guò)的項(xiàng)目中,一個(gè)文件中有好幾十萬(wàn)條記錄。如果一次性將多條記錄讀入,則會(huì)花費(fèi)大量的處理時(shí)間,且占用大量的內(nèi)存。為此,要求對(duì)于包含大量數(shù)

一、概述

在實(shí)際的軟件開(kāi)發(fā)項(xiàng)目中,經(jīng)常需要處理大量的文件。某些文件中包含了相當(dāng)多的數(shù)據(jù)記錄數(shù),如作者本人參與過(guò)的項(xiàng)目中,一個(gè)文件中有好幾十萬(wàn)條記錄。如果一次性將多條記錄讀入,則會(huì)花費(fèi)大量的處理時(shí)間,且占用大量的內(nèi)存。為此,要求對(duì)于包含大量數(shù)據(jù)記錄的文件進(jìn)行分批讀取操作,即每一輪讀取一定數(shù)目的數(shù)據(jù)記錄,待將這些記錄處理完成之后,再讀取下一批數(shù)據(jù)。本文介紹分批讀取文件中數(shù)據(jù)的程序流程,并給出了C程序?qū)崿F(xiàn)。

二、總體程序流程

實(shí)現(xiàn)分批讀取文件中數(shù)據(jù)的程序流程如圖1所示。

                            圖1 實(shí)現(xiàn)分批讀取文件中數(shù)據(jù)的程序流程

三、C程序?qū)崿F(xiàn)

本程序命名為BatchReadFile.c,具體代碼如下:

/**********************************************************************
* 版權(quán)所有 (C)2015, Zhou Zhaoxiong。
*
* 文件名稱(chēng):BatchReadFile.c
* 文件標(biāo)識(shí):無(wú)
* 內(nèi)容摘要:分批讀取文件中的數(shù)據(jù)并打印出來(lái)
* 其它說(shuō)明:無(wú)
* 當(dāng)前版本:V1.0
* 作 者:Zhou Zhaoxiong
* 完成日期:20150528
*
**********************************************************************/
#include <stdio.h>

// 重定義數(shù)據(jù)類(lèi)型
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ù)的最大長(zhǎng)度

// 函數(shù)聲明
INT32 ReadRecordFromFile(FILE *fp, UINT8 szRecordSet[][MAX_RECORD_LEN], UINT32 *piReadCnt);
INT32 main();


/**********************************************************************
* 功能描述:主函數(shù)
* 輸入?yún)?shù):無(wú)
* 輸出參數(shù):無(wú)
* 返 回 值:無(wú)
* 其它說(shuō)明:無(wú)
* 修改日期 版本號(hào) 修改人 修改內(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");

// 打開(kāi)文件
fp = fopen(szFileName, "r");
if (NULL == fp) // 打開(kāi)失敗
{
printf("Open file %s failed!\n", szFileName);
return -1;
}

// 讀取文件內(nèi)容并打印出來(lá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-讀取失敗
* 其它說(shuō)明:無(wú)
* 修改日期 版本號(hào) 修改人 修改內(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}; // 存儲(chǔ)讀取到的每條記錄信息
UINT32 iRecordLen = 0; // 存儲(chǔ)讀取到的每條記錄信息的長(zhǎng)度

if (fp == NULL || piReadCnt == NULL)
{
printf("ReadRecordFromFile: input paramter(s) is NULL!\n");
return -1;
}

// 讀取文件記錄
while ((!feof(fp)) && (!ferror(fp))) // 遇到文件結(jié)尾或讀取錯(cuò)誤則退出
{
// 讀取一條記錄
memset(szRecordInfo, 0x00, sizeof(szRecordInfo));
fgets(szRecordInfo, sizeof(szRecordInfo)-1, fp);

// 去掉記錄后面的回車(chē)換行符
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;
}

四、程序說(shuō)明

1.被讀取的文件命名為“TestFile.txt”,存放在“/home/zhou/zhouzx/test/file/”目錄下。

2.為了方便看到效果,程序中設(shè)定每一次最大讀取條數(shù)為5,每條記錄的最大長(zhǎng)度為50(最大長(zhǎng)度值的設(shè)定的依據(jù)是讀取的文件記錄的長(zhǎng)度)。將讀取到的記錄存放到一個(gè)二維數(shù)組變量中,其中第一維是每次讀取到的記錄條數(shù),第二維是每條記錄的長(zhǎng)度。

3.如果一輪未讀完數(shù)據(jù),則文件指針會(huì)自動(dòng)跳到下一次讀取的記錄的開(kāi)頭。結(jié)束一輪讀取的條件有三個(gè):已達(dá)讀取上限、記錄已全部讀完、讀取錯(cuò)誤。

4.如果文件中出現(xiàn)了空行,那么程序并不會(huì)將之作為有效行而使得讀取條數(shù)增加,而是從下一個(gè)非空行開(kāi)始繼續(xù)計(jì)數(shù)。

5.程序會(huì)打印出讀取的次數(shù)及每次讀取到的具體記錄信息,方便查看程序分批處理的執(zhí)行情況。

五、程序編譯及運(yùn)行結(jié)果

在Linux下,使用“gcc -g -o BatchReadFile BatchReadFile.c”命令對(duì)程序進(jìn)行編譯,生成“BatchReadFile”。下面執(zhí)行“BatchReadFile”命令來(lái)對(duì)程序進(jìn)行測(cè)試。

1.“TestFile.txt”文件中的內(nèi)容如下:

100001
100002
100003
100004

則程序運(yùn)行結(jié)果為:

ReadTimes is: 1, the RecordInfo is:
100001
100002
100003
100004

2.“TestFile.txt”文件中的內(nèi)容如下:

100001
100002
100003
100004
100005

則程序運(yùn)行結(jié)果為:

ReadTimes is: 1, the RecordInfo is:
100001
100002
100003
100004
100005

3.“TestFile.txt”文件中的內(nèi)容如下:

100001
100002
100003
100004
100005
100006

則程序運(yùn)行結(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

則程序運(yùn)行結(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àn),即使文件中存在空行,程序也能夠正常處理。

六、總結(jié)

本文對(duì)分批讀取文件中數(shù)據(jù)的程序流程進(jìn)行了介紹,并給出了C程序?qū)崿F(xiàn)。在實(shí)際的軟件開(kāi)發(fā)項(xiàng)目中,每個(gè)文件包含的記錄條數(shù)要多很多,但基本的程序編寫(xiě)流程是一樣的。大家可以根據(jù)實(shí)際需要對(duì)本文中的程序進(jìn)行修改來(lái)滿(mǎn)足具體的要求。

往期精彩


五分鐘讀懂TCP 協(xié)議

為L(zhǎng)inux應(yīng)用構(gòu)造有限狀態(tài)機(jī)

專(zhuān)為MCU項(xiàng)目開(kāi)發(fā)提速的代碼框架BabyOS

嵌入式C語(yǔ)言代碼優(yōu)化方案(深度好文,建議花時(shí)間研讀并收藏)

stm32cubeMX學(xué)習(xí)、USB DFU(Download Firmware Update)固件更新

若覺(jué)得本次分享的文章對(duì)您有幫助,隨手點(diǎn)[在看]并轉(zhuǎn)發(fā)分享,也是對(duì)我的支持。

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專(zhuān)欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉
關(guān)閉