C/C++中讀取檔案判斷是否讀取結束
阿新 • • 發佈:2019-02-16
最近用C++讀取檔案時遇到了一個問題,讀取如下圖所示的檔案時,使用C中的feof()判斷是否讀取結束,總會在檔案末尾處總會多讀一遍。
可以看到我讀取的檔案格式是比較簡單的,沒兩行為一對,第一行有兩個int型別的數字,第二行是一個字串,包含影象的名稱。
先上我讀取檔案的程式碼:
void read(string name) { FILE *file = fopen(name.c_str(), "r"); while (!feof(file)) { int i, j; fscanf(file, "%d%d\n", &i, &j); char filename[100]; fgets(filename, 100, file); filename[strlen(filename) - 1] = '\0'; } }
可以看到,讀取的程式碼非常簡單,但是這樣會出現一個問題,最後一行會重複輸出一遍。
造成這個問題的原因在於feof在真正檔案讀取結束後還會繼續在判斷一遍才會結束。
為了解決這個問題,有人是使用瞭如下方法
char c;
c = fgetc(fp);
while(!feof(fp))
{
printf("%X/n", c);
c = fgetc(fp);
}
printf("%X/n", c);
c = fgetc(fp);
}
這種方法確實可以避免重複讀取最後一行的問題,但是這種方法更加適合於每次讀取單個字元的情況,對於我遇到的這種,需要讀取int和字串的情況就不是很適用,最終我在網上找到了一種萬無一失的方法解決feof的問題,那就是不用它。。。
我們適用fseek和ftell來配合判斷是否讀取到檔案末尾。
void read(string name) { FILE *file = fopen(name.c_str(), "r"); fseek(file, 0L, SEEK_END); long end = ftell(file); fseek(file, 0L, SEEK_SET); long start = ftell(file); while (end != start) { int i, j; fscanf(file, "%d%d\n", &i, &j); char filename[100]; fgets(filename, 100, file); if (filename[strlen(filename) - 1] == '\n') filename[strlen(filename) - 1] = '\0'; cout << filename << endl; start = ftell(file); } }
大體思路就是首先通過fseek得到檔案末尾的位置,然後在讀取檔案以後不斷計算當前讀取的檔案位置,如果讀取後發現當前位置與檔案末尾位置相同,則停止繼續讀取檔案。
這種方法的好處是萬金油,記住這一種,以後遇到所有需要讀取全部檔案的情況都可以適用。簡單易懂。
當然利用C++的方法也可以實現這一需求,但是有些情況下C++的讀寫速度明顯低於C語言,而且C++相容C語言。