使用fread产生垃圾

Produce garbage with using of fread

本文关键字:fread 使用      更新时间:2023-10-16

我想用fread从文件中读取数据。然而,我遇到了设置NULL终止符的问题。我认为行(fileMem[fileSize]=0;)应该已经解决了。然而,我在检查"fileMem"的值时仍然会收到垃圾。有人能帮我找出问题吗?

我关注了其他关于设置NULL终止符的帖子,但不起作用

File *input = fopen(filePath, "r");
fseek(input, 0, SEEK_END);
auto fileSize = ftell(input);
fseek(input, 0, SEEK_SET);
char* fileMem = new char[fileSize+1];
fileMem[fileSize] = 0;// the NULL terminator problem should have been solved here
clearerr(input);
fread(fileMem, fileSize,1, input);

我的代码有什么问题?

fread读取的字节数超过fileSize,因为您指定了fileSize的记录大小,并要求它只读取一条文本记录。然后,它用实际数据覆盖末尾的0,这样就得到了垃圾。

fread返回它实际读取的字节数,因此您可以分配一个更大的缓冲区,然后使用fread的返回值来确定其中有多少是有效的(并设置一个null终止符)。

由于它以这种方式更新您的数据,我还建议将文件类型更改为二进制(在对fopen的调用中为"rb"而不是"r")。

之所以会发生这种情况,是因为fread在文本模式下("r"而不是"rb")执行文本翻译,例如回车和换行。

假设您在Windows上,我认为问题在于您以文本模式打开文件,并使用适用于二进制模式的fread。在文本模式下,您读取的内容可能与文件中的内容不完全相同。Windows文本文件的末尾有"\r\n",但在文本模式下,这两个字符的组合会转换为一个字符"\n"。因此,您计算的fileSize将过大,因此您的null终止符将位于错误的位置。

要验证这一点,请将您的fread更改为:

int nr = fread( fileMen, 1, fileSize, input);

交换中间的参数,将使fread返回读取的字节数。如果您查看nr的值,由于行尾平移,它将小于fileSize

这在*nix系统上不会有问题,因为在文本模式下没有翻译。

如果要使用fread读取文件的内容,则必须以二进制模式打开该文件。

FILE *input = fopen(filePath, "rb");
                                ^^

否则,使用获得的文件大小

fseek(input, 0, SEEK_END);
auto fileSize = ftell(input);

将大于CCD_ 8可以读取的字符数。

如果您有一个CR和一个LF,通过上述方法,它们将算作两个字符,但fread将只读取一个字符。因此,fread将读取少于fileSize的字符。您也可以将fread行更改为:

// Swap the middle arguments.
// The first argument is supposed to be the size of each object.
// The second argument is supposed to be the number of objects to read.
auto n = fread(fileMem, 1, fileSize, input);
if ( n != fileSize )
{
   // Surprise
}
fileMem[n] = '';