ifstream(一)之 eof() 函数——解决读取文件最后一个数据多读一次的方法

原文地址:http://hi.baidu.com/wcmxiaolizi/item/5e304e5da4c5a6b2adc85700



对于文件的操作中主要有几种,无非就是写入、读取罢了。

打开文件时,主要有几种模式 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;

  • 7
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值