【问题标题】:Why does fread() in c read extra '#newlines' characters?为什么 c 中的 fread() 会读取额外的“#newlines”字符?
【发布时间】:2016-11-08 09:11:27
【问题描述】:

当我尝试使用 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  

我看到了其他一些测试用例。在每个测试用例中,额外的字符数总是换行数。
我有几个问题:
-为什么图案是这样的?
- 这与新行在 Windows 中占用 2 个字节这一事实有什么关系?
-如何摆脱那些多余的字符?
我搜索了类似的问题,但没有找到答案。请有人解释一下吗?

【问题讨论】:

  • 为什么?因为这正是文件中的内容。换行符 (\n) 需要在那里表示换行。有很多方法可以摆脱换行符。最好的方法取决于您要达到的目标。参见例如Removing trailing newline character from fgets() input
  • 请显示您文件的确切内容。
  • 另外,您为什么不使用您专门定义的LEN,而不是在fread()call 中输入号码?
  • DOS换行符是CR+LF
  • fread 不用于阅读文本,fgets 是更好的选择。

标签: c file-io fread


【解决方案1】:

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

函数fread的用法不正确,大小和计数参数切换。这意味着读取始终是部分的,因为您的文件中没有 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 The ftell function 2)
对于文本流,其文件位置指示符包含未指定 信息,可由 fseek 函数用于返回文件位置指示符 流到 ftell 调用时的位置;两个这样的区别 返回值不一定是衡量写入或读取字符数的有意义的指标。

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2015-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-07
      • 2018-02-07
      • 1970-01-01
      相关资源
      最近更新 更多