ifstream(一)之 eof() 函数——解决读取文件最后一个数据多读一次的方法
2014-06-04 16:51
555 查看
原文地址:http://hi.baidu.com/wcmxiaolizi/item/5e304e5da4c5a6b2adc85700
对于文件的操作中主要有几种,无非就是写入、读取罢了。
打开文件时,主要有几种模式 ios::in,ios::binary,ios::app,ios::trunc,ios::ate但并不是每种模式都是适用于ifstream 类的,我们也可以使用组合模式的方式来打开文件.
在读取文件时我们要特别注意一个函数 eof()该函数当文件指针到达文件尾时就返回为true,否则返回false;但是我们用它的时候却会有一些奇怪的事情发生,参考以下代码:
多输出了一个 '!' ,难道是eof的设计有误?
如果没有错误为什么符号 '!'输出了两次呢?为了详细的说明问题,我们在while循环中加入一点错误的验证处理机制;
修改成以下代码:
由此可见在文件读取完符号 '!'之后并没有立即到达文件尾指针。
代码 ifile>>c;读取失败,但是并没有破坏 char c;的数据(内部肯定临时存在一个变量 char temp;)
所以多输出了一个 '!';
在来看另外一个例子,这个例子是操作二进制文件的例子:
由此可见确实是eof();函数在读取完最后一组数据时,它还读取了一个什么东西(多多读取了一次),所以在使用该函数的是请增加一个处理,即
if( xxx.fail() )
{
编写你处理方案
...
}
还要在说一句read读取失败时,并没有破坏数据temp(其实现内部肯定有一个临时变量)
编程经验:
常用打开模式(有效组合)组合有
ios::in|ios::binary;//读取以二进制文件格式,并允许使用插入符>>
ios::in|ios::app;//打开文件且添加输出,并允许使用插入符>>
ios::in|ios::ate;//读取文本文件且文件指针一直寻找定位到EOF结束符,并允许使用插入符>>
ios::in|ios::trunc;//打开文件并清空内容,并允许使用插入符>>
...
要注意有一些模式组合是没有意义的(画蛇添足)例如:
ios::in::ios::out;
对于文件的操作中主要有几种,无非就是写入、读取罢了。
打开文件时,主要有几种模式 ios::in,ios::binary,ios::app,ios::trunc,ios::ate但并不是每种模式都是适用于ifstream 类的,我们也可以使用组合模式的方式来打开文件.
在读取文件时我们要特别注意一个函数 eof()该函数当文件指针到达文件尾时就返回为true,否则返回false;但是我们用它的时候却会有一些奇怪的事情发生,参考以下代码:
#include <cstdlib> #include <iostream> #include <fstream> using namespace std; int main(int argc, char *argv[]) { const char* filename="temp.txt"; ifstream ifile(filename); if( !ifile ) { cout<<"打开文件失败"<<endl; system("pause"); } char c; while( !ifile.eof() ) { ifile>>c; cout<<c; } cout<<endl; cout << "Press the enter key to continue ..."; cin.get(); return EXIT_SUCCESS; }
多输出了一个 '!' ,难道是eof的设计有误?
如果没有错误为什么符号 '!'输出了两次呢?为了详细的说明问题,我们在while循环中加入一点错误的验证处理机制;
修改成以下代码:
if( ifile.fail() ) cout<<"\n文件读取错误"<<endl; cout<<c;
由此可见在文件读取完符号 '!'之后并没有立即到达文件尾指针。
代码 ifile>>c;读取失败,但是并没有破坏 char c;的数据(内部肯定临时存在一个变量 char temp;)
所以多输出了一个 '!';
在来看另外一个例子,这个例子是操作二进制文件的例子:
#include <cstdlib> #include <iostream> #include <fstream> using namespace std; struct Node { int key; char mean[10]; }; typedef Node node; node name[]= { {1,"one"}, {2,"tow"}, {3,"three"}, {4,"fore"}, {5,"five"}, {6,"six"}, {7,"siven"}, {8,"eight"}, {9,"nie"}, {10,"ten"} }; int main(int argc, char *argv[]) { const char* filename="temp.dat"; node temp; //写入文件... ofstream ofile(filename,ios::out|ios::binary); if( !ofile ) { cout<<"文件写入失败..."<<endl; system("pause"); } for( int i=0; i < 10; i++ ) { temp=name[i]; ofile.write((char*)&temp,sizeof(temp)); }//end for ofile.close(); //读取文件... ifstream ifile(filename,ios::in|ios::binary); if( !ifile ) { cout<<"读取文件失败..."<<endl; system("pause"); } while( !ifile.eof() ) { ifile.read((char*)&temp,sizeof(temp)); cout<<temp.key<<" "; cout<<temp.mean<<endl; }//end while ifile.close(); cout << "Press the enter key to continue ..."; cin.get(); return EXIT_SUCCESS; }
由此可见确实是eof();函数在读取完最后一组数据时,它还读取了一个什么东西(多多读取了一次),所以在使用该函数的是请增加一个处理,即
if( xxx.fail() )
{
编写你处理方案
...
}
还要在说一句read读取失败时,并没有破坏数据temp(其实现内部肯定有一个临时变量)
编程经验:
常用打开模式(有效组合)组合有
ios::in|ios::binary;//读取以二进制文件格式,并允许使用插入符>>
ios::in|ios::app;//打开文件且添加输出,并允许使用插入符>>
ios::in|ios::ate;//读取文本文件且文件指针一直寻找定位到EOF结束符,并允许使用插入符>>
ios::in|ios::trunc;//打开文件并清空内容,并允许使用插入符>>
...
要注意有一些模式组合是没有意义的(画蛇添足)例如:
ios::in::ios::out;
相关文章推荐
- c++中ifstream一次读取整个文件
- c++中ifstream一次读取整个文件
- 使用ifstream的get()函数读取文件中的字符后输出时,最后一个字符多输出一次
- 用c#读取excel文件缺少第一行数据解决方法
- 关于C语言fprintf()函数将纯数据写入文件速度慢的解决方法
- php使用fputcsv()函数csv文件读写数据的方法(解决中文乱码问题)
- 文件操作ofstream,open,close,ifstream,fin,依照行来读取数据, fstream,iosin iosout,fio.seekg(),文件写入和文件读写,文件拷贝和文件
- ifstream 流 判断文件是否结尾的函数eof()
- c++中ifstream一次读取整个文件
- ifstream或ofstream打开带有中文路径的文件失败解决方法
- C++ 输入流 cin/ ifstream/ istringstream 及几个相关函数在遇到文件结束符EOF时的行为
- 用c#读取excel文件缺少第一行数据解决方法
- c++中ifstream一次读取整个文件
- ifstream 流 判断文件是否结尾的函数eof()
- c++中ifstream一次读取整个文件
- c++中ifstream一次读取整个文件
- jxl读取excel文件异常:Unable to recognize OLE stream 的解决方法
- 文件操作ofstream,open,close,ifstream,fin,按照行来读取数据, fstream,iosin iosout,fio.seekg(),文件写入和文件读写,文件拷贝和文件
- 转自【北漂民工】C++文件读取操作的全部函数讲解fstream(ofstream/ifstream)
- c++中ifstream一次读取整个文件