有關fgetc配合feof逐行讀取文件最後OA現金盤平臺出租一行讀取兩遍的錯覺
最近在做一個wifiap設置的接口,用戶首先獲取到當前wifi 熱點的ssid 和pwd,然後修改,保存。
獲取信息的時候是fopen對應的hostapd.conf文件,逐行讀取,查找匹配的參數。
修改的時候則是逐行讀取當前hostapd.conf文件,逐行寫到新的臨時配置文件裏面,如果匹配到ssid或者pwd則修改成新的值再寫到新文件裏面。
最後將新的臨時配置文件rename成hostapd.conf。
測試的時修改完後,cat出hostapd.conf的檢查發現最後一行總是重復兩遍。
雖然不影響整體功能,但是非常出乎意料,超出預期設計的效果。
讀取更新的代碼邏輯大致如下
復制代碼
while (!feof(srcF))
{
//get line data
fgets(tmp, sizeof(tmp), srcF);
f = tmp;
LOGD("get %s",f);
//clear space in the head while(‘ ‘ == *f || ‘\n‘ == *f || ‘\r‘ == *f) f++; if(‘\0‘ == *f) continue; //if the comments copy directly if(‘#‘ == *f) { LOGD("get comments %s", f); fputs(f, dstF); continue; } p = strstr(f, WIFI_SSID); //we must makesure it is start with my str if(p == f) { //replace new ssid name p += strlen(WIFI_SSID); sprintf(p,"%s\n", ssid); LOGD("replace new ssid %s",f); fputs(f, dstF); continue; } p = strstr(f, WIFI_PW); //we must makesure it is start with my str if(p == f) { //replace new password p += strlen(WIFI_PW); sprintf(p,"%s\n", pw); LOGD("replace new pwd%s",f); fputs(f, dstF); continue; } else fputs(f, dstF); LOGD("copy %s",f);
復制代碼
大概看一下總體的循環邏輯是沒錯
【判斷是否到了文件結束-->讀取一行內容-->將讀取的內容寫到新的文件中】
但是仔細查條件檢查和返回值的判斷,還是發現忽略了一些細節。
1、讀完了最後一行還沒讀到EOF,需要下一次讀取才到EOF。
2、沒有對fgets返回值進行判斷,最後一次讀完再去讀取的時候會返回NULL。
3、沒有對讀取數據的tmp buf進行清空處理。
事實上最後一次沒讀到東西,只是tmp裏面的數據是上一次讀取沒有清空的,所以造成了重復讀取的錯覺。
解決方法如下:
1、判斷fgets返回值,如果是NULL則continue返回去繼續判斷eof
復制代碼
while (!feof(srcF))
//get line data
if(NULL == fgets(tmp, sizeof(tmp), srcF))
continue;
...........
}
復制代碼
2、先讀取後判斷eof
復制代碼
while (1)
{
//get line data
fgets(tmp, sizeof(tmp), srcF);
if(feof(srcF))
break;
................
}
復制代碼
以上經過驗證ok。
另外最好在每次使用buf前都進行一次memset,清空緩存。
有關fgetc配合feof逐行讀取文件最後OA現金盤平臺出租一行讀取兩遍的錯覺