fgets()重复读取最后一行的分析及解决方法

来源:互联网 发布:c#仓库管理系统源码 编辑:程序博客网 时间:2024/05/16 13:34

      使用 fgets() 读取一个文本文件的时候,如果读取的 方法不恰当,就有可能造成重复读取最后一行的问题。具体如下。

      (1) 在 Windows 平台上, 假设有 test.txt ,内容如下:

this is line 1this is line 2this is line 3this is line 4

      使用传统的读取方法:

while( ! feof(fp) ){char tmp[100] ;fgets( tmp , 100 , fp );cout<<tmp<<endl;}

     结果如下:

  

       然而,换成 Linux 平台,就有不同的运行结果,如下:

      


     (2)我们使用另一种读取方法:

      

/* 改进的读取txt文件的方式 */while( true ){char tmp[100];fgets( tmp , 100 , fp );if( feof(fp) )break;cout<<tmp<<endl;}

       在 Windows平台上,运行结果如下:

     

      很明显,最后一行没有被读取。

      换成 Linux 平台,再次执行,结果如下:

     

      (3) 现象原因分析

       引用网上大牛的解释:

       feof是ANSI标准定义的:在遇到文件结束时返回非0值。
       对于象DOS系统,这比较方便。因为文件有明确的结束标志EOF。
       对于UNIX,就稍微麻烦一点。因为文件没有结束标志,只有通过当前指针和文件长度来判断文件是否结束。当 read 时,先调用trap进入核心态,由FILE->;ile->;inode,取得文件的物理地址,然后取得文件的剩余的长度,比较该长度是否为0,如果为0则置文件结束标志;如果不为0,则比较该长度和要读的长度,取其中的小值,并将文件内容读入用户地址。
       具体到我们所遇到的现象就比较清晰了,读文件最后一行的fgets(也是调用read的)被调用的时候,该文件的剩余长度不为0,所以不置文件结束标志。而再fgets时,文件的剩余长度为0,文件结束标志被置且马上返回。


      (4)兼容 windows 和 Linux 的文件读取方式

          分析了现象和原因,最后给出一种在Windows和Linux上都能够正确读取文本的方法。

         

        /* 统一的的读取txt文件的方式 */char tmp[100] ;while( fgets(tmp , 100 , fp ) != NULL ){cout<<tmp<<endl;}

       在 Windows 下,执行结果:

  

     在 Linux 下,执行结果:

    

     实验表明,这种读取方法在两种平台都能正确地读取。

     参考资料:http://stackoverflow.com/questions/14615671/whats-the-real-reason-to-not-use-the-eof-bit-as-our-stream-extraction-condition

1 0
原创粉丝点击