为什么 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);
当我尝试使用 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);