为什么c中的fread()会读取额外的'#newlines'字符?

时间:2016-07-06 10:35:43

标签: c file-io fread

当我尝试使用 fread()将文件复制到字符串时,我从文件中获取额外的字符,这与新行的数量完全相同。 这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#define LEN 5000000

int main()
{
   char *in = (char*) malloc(LEN);
   FILE *f=fopen("in.txt","r");
   fread(in,5000000,1,f);
   printf("%ld\n", ftell(f)); 
   in[ftell(f)]=0;
   int l;
   for(l=0;true;l++)
   {
      if(in[l]<10)
        break;
      printf("%d ",in[l]);
   }
   printf("\n");
}

此计划的输入是:

1  
2  
<newline>

输入链接:https://paste.fedoraproject.org/388281/46780193/
对于输出,我打印字符的ASCII值读取:

6  
49 10 50 10 13 10  

如果输入为:

1  
2  
3  
<newline>  

输入链接:https://paste.fedoraproject.org/388280/
然后输出是:

9  
49 10 50 10 51 10 51 13 10  

我看到了其他一些测试用例。在每个测试用例中,额外的字符数始终是新行的数量 我有几个问题:
为什么这种模式是这样的呢? - 这是否与新行在窗口中占用2个字节这一事实有关? - 如何摆脱那些额外的角色?
我搜索了类似的问题,但没有找到答案。请有人解释一下吗?

2 个答案:

答案 0 :(得分:2)

在以文本模式打开的流上调用ftell,例如在您的示例中没有意义 1

函数fread的用法不正确,size和count参数被切换。这意味着读取始终是部分的,因为您的文件中没有5000000个字符。因此,调用后数组中元素的值具有不确定的 2 值。 (在您的情况下,逻辑元素是一个大小为5000000的单个元素。)

您所看到的结果并不重要。读取不确定的值可能会导致未定义的行为。

读取文件的正确方法是将正确的参数传递给fread并使用返回值来确定成功读取的字符数:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>

int main()
{
    unsigned char in[500] = { 0 } ;
    FILE *f=fopen("in.txt","r");
    assert( f ) ;

    const size_t read = fread(in,1,500,f);
    printf( "read: %zu\n" , read );

    for( size_t index = 0 ; index < read ; index++ )
    {
        printf( "%hhu " , in[index] );
    }

    fclose( f );
}

使用这个正确的程序,当文件包含内容时(点不是文件的一部分):

.
1
2
3

.

将读取并打印正确的值:

read: 7
49 10 50 10 51 10 10

一个换行符,每个数字用值10表示 3 ,最后加一个换行符。

1 (引用自:ISO:IEC 9899:201x 7.21.9.4 ftell功能2)
对于文本流,其文件位置指示符包含未指定 信息,可由fseek函数用于返回文件位置指示符 在ftell电话时流到它的位置;两个这样的区别 返回值不一定是写入或读取的字符数的有意义的度量。

2 (引自:ISO:IEC 9899:201x 7.21.8.1 fread功能2)
如果读取了部分元素,则其值是不确定的。

3 在Windows文件中,换行符由两个字符表示:13,10。回车符和换行符。但是当以文本模式阅读文件时,换行符始终只是换行符:10。由于程序的行为没有意义,因此您看到了字符13。如果您(正确地)打开并以二进制模式读取文件,您将看到由两个字符表示的换行符。

答案 1 :(得分:-1)

如果您正在使用Windows并使用某个编辑器编辑文件in.txt,该编辑器将CR-LF(回车,LINE-FEED)((ASCII)13,10)附加到每个换行符,这肯定会发生。尝试通过程序编写in.txt然后阅读它。这将按预期进行。或者使用没有将CR-LF附加到eol(行尾)的编辑器。抱歉,我不知道没有这样的编辑器[但是有些Linux编辑器会工作。]。