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

Why does fread() in c read extra '#newlines' characters?

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

link 输入:https://paste.fedoraproject.org/388281/46780193/
对于输出,我正在打印字符的 ASCII 值:

6  
49 10 50 10 13 10  

如果输入是:

1  
2  
3  
<newline>  

link 输入:https://paste.fedoraproject.org/388280/
那么输出是:

9  
49 10 50 10 51 10 51 13 10  

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

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

函数fread的用法不正确,大小和计数参数调换了。这意味着读取总是部分的,因为您的文件中没有 5000000 个字符。因此调用后数组中元素的值具有不确定的2 值。 (您的案例中的逻辑元素是大小为 5000000 的单个元素。)

您看到的结果没有意义。读取不确定的值可能会导致未定义的行为。

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

#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 函数用于 returning 的文件位置指示符 在 ftell 调用时流到它的位置;两个这样的区别 return 值不一定是对写入或读取的字符数的有意义度量。

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

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

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

我不知道它如何影响程序流程,但我遇到了同样的问题,直到我将文件访问模式从 "r" 更改为 "rb",尽管那仍然是纯文本文件。

所以;除了用户@2501 的建议(已接受的答案)之外,还应考虑这一点以及以下几行

FILE* ptrFile = fopen("fileName.txt", "r");
fread(in, 500, 1, ptrFile);

应该更正为

FILE* ptrFile = fopen("fileName.txt", "rb");
fread(in, 1L, 500, ptrFile);