问题:
来自:http://topic.csdn.net/u/20100103/00/99f1111e-aebc-496d-bcb2-889bbe82f091.html
如下:
#include <iostream> #include<fstream> using namespace std; int main() { ofstream ofs("a.txt"); int n = 10; while (--n) ofs<<n<<"/t"; ofs<<endl; ofs.close(); int x,y = 0, z = 0; ifstream ifs("a.txt"); while (!ifs.eof()) { ifs>>x; ++z; cout<<x<<"/t"<<flush; //问题在这里,文件流已经结束了,怎么还要循环一次呢? }// 上面写入到文件里面的是9 8 7 6 5 4 3 2 1,读出来怎么变成了 cout<<endl; ifs.close(); //9 8 7 6 5 4 3 2 1 1了呢?多循环了一次呀!! }
原因:
刚好读到文件尾的时候,并不会设置文件结束的标志位,只有再读取一个字节(由于到了文件尾了,所以,读取会失败)时,才会设置文件结束标志位。
因此,上面的程序,读取到文件结尾,所有的内容已经输出,然后再判断,此时文件结束标志并没有置位。然后再读取一个字符的时候,就进行了错误的读取,出错了,才会置位(eof()判断的是个出错的情况啊),读取也失败了,所以x里面的内容仍然是上一次读取的内容:1。
再考虑这样的情形,使用read函数每次读固定的数据大小的数据,如果最后读取的字节不够了的话,那么在最后这次读取时,文件结束标志就会置位,因为“发生了读取失败”的情况,所以要设置标志以表示这次的“错误”。
因此,对于read函数的使用,一般判读其返回值是不是0后者是不是等于要读取字节数,来判断是否到达文件结尾。参考代码如下:
#include <iostream> #include <fstream> #include <string> using namespace std; const int BUFSIZE = 1024 * 1024; void CopyRawFile(string InFile, string OutFile) { char* pchar = new char[BUFSIZE]; ofstream ofile; ifstream ifile; ofile.open(OutFile.c_str(), ios::binary); ifile.open(InFile.c_str(), ios::binary); while(ifile.read(pchar, BUFSIZE)) ofile.write(pchar, BUFSIZE); ofile.write(pchar, ifile.gcount()); ifile.close(); ofile.close(); delete []pchar; }
另外,有位仁兄对c语言的文件结束的判断做了相同的解释:http://blog.csdn.net/pang123hui/archive/2010/02/21/5315180.aspx