C - fwrite - 无法打开文件,因为它包含无效字符

C - fwrite - can't open file because it contains invalid characters

我正在使用 C 的 fwrite 函数将 3 个整数的数组写入文件,但是当使用 gedit(使用 Unicode UTF-8)打开输出文件时,出现以下错误:

There was a problem opening the file.  The file you opened has invalid characters.  If you continue editing this file, you could corrupt the document.

这是相关的代码片段:

char* imageFile = "image.txt";
FILE* imageFilePtr = fopen(imageFile, "w");

int scores[3] = {69, 70, 71};
fwrite(scores, sizeof(int), sizeof(scores), imageFilePtr);

当我使用十六进制 reader 例如 "xxd" 时,我在终端中得到以下信息:

0000000: 4500 0000 4600 0000 4700 0000 7031 7108  E...F...G...p1q.
0000010: 0830 7108 2987 0408 2087 0408 0460 cebf  .0q.)... ....`..
0000020: 0100 0000 0000 0000 0000 0000 0000 0000  ................

请记住,在我的环境中,sizeof(int) 是 4 个字节。因此,我可以看到如何将十进制的 69、70 和 71 作为十六进制的 45、46 和 47 打印到文件中,如 xxd 所示。但是,“4700 0000”之后的所有其他字节来自哪里?而且,为什么我不能用文本编辑器打开输出文件 "image.txt" 来查看显示十进制数字 69、70 和 71 的文件?

fwrite(scores, sizeof(int), sizeof(scores), imageFilePtr);
                            ^^^^ Wrong

在你的例子中,sizeof(scores)sizeof(int)*3。你只需要3个,你可以使用:

fwrite(scores, sizeof(int), 3, imageFilePtr);

或者为了更稳健,使用:

fwrite(scores, sizeof(int), sizeof(scores)/sizeof(int), imageFilePtr);

您还可以使用:

fwrite(scores, 1, sizeof(scores), imageFilePtr);

fwrite(scores, sizeof scores[0], sizeof scores/sizeof scores[0], imageFilePtr);

这里有两个问题。一种是您正尝试在文本编辑器中打开二进制文件。第二个是写入二进制文件时缓冲区读取溢出。 我先说第二个。

fwrite 函数接受一个"size of element" 和一个"count of elements" 作为参数。您已将元素的大小设置为正确的 sizeof(int),但是对于您所做的计数 sizeof(scores) 实际上是 3*sizeof(int),而您实际上需要值 3。假设 int 大小为 4 (32 位)然后计数值被设置为 12。这意味着它正在尝试将 48 个字节而不是 12 个字节写入文件。另外 36 个字节是堆栈上的读取溢出。

要获取数组中元素的数量,您可以使用:sizeof(scores)/sizeof(scores[0])。

fwrite(scores, sizeof(int), sizeof(scores)/sizeof(scores[0]), imageFilePtr);

我会为此使用一个宏,这样我就可以去

fwrite(scores, sizeof(int), NumOfElements(scores), imageFilePtr);

其中 NumOfElements 定义为:

#define NumOfElements(Array) (sizeof(Array)/sizeof(Array[0]))

现在解决第一个问题。我相信您正在尝试将 3 个整数写入文本文件。 fwrite 函数写入二进制数据。您要使用的是 fprintf。这与 printf 的工作方式相同,但可以让您写入文件。但是你不能用一个 fprintf 写一个数字数组,所以你必须有一个循环。

for( i=0; i<NumOfElements(scores); i++ )
{
    fprintf( imageFilePtr, "%u\n", scores[i] );
}

这会将每个数字写入单独一行的文件中。