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

时间:2015-10-07 21:31:30

标签: c file-io hex fwrite xxd

我正在使用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);

当我使用十六进制阅读器如“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如何以xxd显示的十六进制中的45,46和47打印到文件中。但是,“4700 0000”之后的所有其他字节从何而来?而且,为什么我不能打开输出文件“image.txt”,用文本编辑器查看显示内部写入的十进制数字69,70和71的文件?

2 个答案:

答案 0 :(得分:5)

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);

答案 1 :(得分:1)

我可以在这里看到两个问题。一个是你试图在文本编辑器中打开二进制文件。第二个是在写二进制文件时有一个缓冲区读溢出。 我先解决第二个问题。

fwrite函数将“元素大小”和“元素数”作为参数。你已经将元素的大小设置为sizeof(int)这是正确的,但是对于计数你已经完成了sizeof(得分),实际上是3 * sizeof(int),而你实际上需要值3.假设int size是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] );
}

这会将每个数字写在一个单独的行中。