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

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

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

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

      使用传统的读取方法:

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

     结果如下:

   fgets()重复读取最后一行的分析及解决方法_第1张图片

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

       fgets()重复读取最后一行的分析及解决方法_第2张图片


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

      

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

		cout<<tmp<<endl;
	}

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

      fgets()重复读取最后一行的分析及解决方法_第3张图片

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

      换成 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 下,执行结果:

   fgets()重复读取最后一行的分析及解决方法_第4张图片

     在 Linux 下,执行结果:

     fgets()重复读取最后一行的分析及解决方法_第5张图片

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

你可能感兴趣的:(windows,linux,重复读取,fgets)