feof()判斷文件結束的問題


我在編寫學生成績管理系統時用到了寫文件和讀文件,發現讀文件總會顯示出亂碼,調試發現是因為用feof()做判斷,在讀文件最后時fread()多讀取了一次。我一開始的解決辦法是每次讀取完文件,都把最后一個節點(每一行數據都讀取放到鏈表的節點里)free掉。但這種方法明顯不是那么好。

feof(fp)用來測試fp所指向的文件當前狀態是否為“文件結束”。如果文件結束,則返回1,否則返回0。適合於二進制文件和文本文件。
但是,在實際使用feof時卻發生了問題:文件實際已經結束時feof還要再判斷一次才返回1
測試代碼如下:

 1 #include <stdio.h>
 2 int main()
 3 {
 4     char ch = 0;
 5     int i = 0;
 6     FILE* fp;
 7     // 建立空文件
 8     fp = fopen("Info.txt", "w");
 9     if(NULL == fp)
10     {
11         printf("Cannot open file!\n");
12         return 0;
13     }
14     fclose(fp);
15     // 讀取空文件
16     fp = fopen("Info.txt", "r");
17     if(NULL == fp)
18     {
19         printf("Cannot open file!\n");
20         return 0;
21     }
22     while(!feof(fp))
23     {
24         ch = fgetc(fp);
25         i++;
26     }
27     fclose(fp);
28     printf("fread times: %d\n"
29             "note: %c\n", i, ch);
30     return 0;
31 }

得到i為1,ch為空,說明feof()確實在文件為空狀態時判斷有誤。

上網搜索有人說先讀再判斷就不會有問題了,但試了一下還是不行。對此,C FAQ-12.3的解釋是“在C語言中,只有輸入例程試圖讀並失敗以后才能得到文件結束符。...fgets()在遇到文件結束符的時候返回NULL。實際上,在任何情況下,都完全沒必要使用feof()。”

把while(!feof(fp)){}換成while(!fgets(str, 0, fp)){}確實能保證判斷正確。但是,如果我在函數體里面還有其他讀操作如fread()的話則會出現影響。所以,最好的解決辦法是利用fseek()和ftell()配合來判斷文件指針位置:

1 fseek(fp, 0L, SEEK_END);//文件指針置於結尾
2 len1 = ftell(fp);//獲取結尾指針值
3 fseek(fp, 0L, SEEK_SET);//文件指針至於開頭
4 len2 = ftell(fp);//獲取開頭指針值
5 while(len2 != len1)//循環判斷
6 {
7     //do something
8     len2 = ftell(fp);
9 }

結果正確,無副作用。

其實還有另一種解決辦法,就是每次寫文件時在開頭寫入節點數,這樣下次讀文件時就知道要讀取多少數據了。

ChinaUnix上也有一篇帖子對於這個問題討論得很詳細,但是提供的方法不適合我當時的情況:http://bbs.chinaunix.net/thread-957347-1-1.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM