【问题标题】:fwrite prints garbage, fread reads garbage structuresfwrite 打印垃圾,fread 读取垃圾结构
【发布时间】:2014-12-10 23:08:57
【问题描述】:

我正在测试二进制文件 i/o。所以,为了练习,我做了一个小程序:

main.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "person.h"

int main()
{
    struct person me;
    struct person cpy_me;
    FILE *dataWrite, *dataRead;

    strcpy(me.fname, "john");
    strcpy(me.lname, "smith");
    me.age = 12;

    printf("%s %s %d\n", me.fname, me.lname, me.age);

    dataWrite = fopen("people.bin", "wb");
    if (fwrite(&me, sizeof( struct person), 1, dataWrite) != 1)
        fprintf(stderr, "Error!\n");
    printf("Wrote to the file\n");

    dataRead = fopen("people.bin", "rb");

    fread(&cpy_me, sizeof(struct person), 1, dataRead);
    printf("%s->Fname\n", cpy_me.fname);
    printf("%s->Lname\n", cpy_me.lname);
    printf("%d->Age\n", cpy_me.age);

    fclose(dataWrite);
    fclose(dataRead);

    return 0;
}

person.h:

#ifndef PERSON_H_INCLUDED
#define PERSON_H_INCLUDED

#define   MAXFIRST    10
#define   MAXLAST     20

struct person
{
    char lname[MAXLAST], fname[MAXFIRST];
    int age;
};
#endif // PERSON_H_INCLUDED

这是文件people.bin中出现的内容:

smith ÿÿb¸tÄ[½tà@ john @ à@                                       

当我阅读显示fread的结果时,我得到了:

我知道在二进制文件中,它不会以人类可读的形式显示,但它应该看起来像这样吗?我不这么认为,因为年龄甚至不可见,fread 显示它读取垃圾。

【问题讨论】:

  • fclose(data);data=fopen("people.bin", "rb");fread(&amp;cpy_me,...
  • 现在我明白了:smith ÿÿb¸tÄ[½tà@ john @ à@
  • fclose(dataWrite); 移动到dataRead = fopen("people.bin", "rb"); 之前。文件关闭后重新打开。
  • 年龄不应该是可见的——整数 12 可能会被写成一个字节的值 12 和三个字节的 0,它们都不能打印。此外,您为每个名称分配了固定数量的空间。内存中超出实际名称长度的任何字节都将出现在输出中,它们可以是任何东西。尝试使用类似“od”(或任何 Windows 等效项——我对 Windows 一无所知)来显示文件。

标签: c struct fwrite fread


【解决方案1】:

这段代码 sn-p 有两个不同的问题:首先,正如 BLUEPIXY 已经评论的那样,您需要关闭并重新打开文件,或者倒带文件,然后再重新读入。否则,您的 fread() 将失败,并且由于未检查程序中的错误,因此您在尝试打印 cpy_me 中的字符串之前不会注意到,这些字符串仍未初始化。

这就涉及到第二个问题:确保将 struct me 初始化为零,例如通过执行struct person me = {"", "", 0}; 这应该处理您在二进制文件中看到的垃圾。 C 中的结构不会自动初始化,除非它们是全局的,或者您明确告诉编译器这样做。

顺便说一句:请注意,像这样进行二进制 I/O 是不可移植的,因为结构在不同架构上可能具有不同的内存布局(要查看这一点,请尝试在 32 位和 64 位模式下重新编译并比较程序生成的二进制文件)。

【讨论】: