2

我试图在多个地方查找它,但我不明白为什么 fwrite 不起作用。

如果我有一个包含 100 个字段的结构,我不想使用带有 100 个格式说明符的 fprintf。

struct emp
{
      char name[15];
      int age;
      int salary;
      char address[30];
};


int main()
{

    char str[60];
    struct emp emp1[5] = {{"Yoda",23,45000,"Asia"},{"Darth",34,2344,"NAmerica"},{"Jabba",22,5566,"Africa"},{"Luke",33,3399,"SAmerica"},{"Laya",44,6677,"Europe"}};

    FILE *fp;
    fp = fopen("C:/.../sampleText.txt","w");`
    int i=0;
   for(i=0; i<5; i++)
   {

            fwrite(&emp1[i],sizeof(emp1[i]),1,fp);

           //fprintf(fp,"%s, %d, %d, %s\n",&emp1[i].name,emp1[i].age,emp1[i].salary,emp1[i].address);
    }

    fclose(fp);
    getch();
 }
4

4 回答 4

3

有两个答案:

  1. 如果一切设置正确并且将写入的数据移植到其他机器不是问题,它确实有效。
  2. 如果您在数据结构中有大量通用特性中的任何一个,或者如果您需要将数据从一种类型的机器(例如 Intel 机器)移动到另一种类型(例如 PowerPC 或 SPARC),则它不起作用。

在您的示例结构中,您没有指针,因此您可以将结构逐字写入文件,然后在同一(类型)机器上运行的程序的另一个调用中,您可以将其读回,您会看到相同的数据。

但是,如果您的结构包含指针,则无法将结构有意义地写入磁盘。程序的一次调用中的指针不需要在程序的另一次调用中具有任何意义。如果您需要在 little-endian (Intel) 和 big-endian (PowerPC, SPARC) 机器之间移植数据,则必须使用平台中立的方式来访问数据;简单地将数据写入磁盘是行不通的。


因此,在可移植性不是问题的情况下,这段代码应该可以工作——Unix 或 Windows。它使用"wb"and"rb"参数,fopen()因为数据是二进制数据,而不是纯文本。在bUnix 上是可选的但无害的;它在 Windows 上至关重要。该代码还修复了文件名,sampledata.bin以便它可以在任一平台上运行,写入当前目录。它写入数据;然后读取数据;然后它将读取的数据与写入的数据进行比较,报告任何问题。如果程序什么也没说,一切都很好。

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

struct emp
{
    char name[15];
    int age;
    int salary;
    char address[30];
};

int main(void)
{
    char const filename[] = "sampledata.bin";
    struct emp emp1[5] =
    {
        { "Yoda",  23, 45000, "Asia"      },
        { "Darth", 34,  2344, "N America" },
        { "Jabba", 22,  5566, "Africa"    },
        { "Luke",  33,  3399, "S America" },
        { "Leia",  44,  6677, "Europe"    },
    };
    struct emp emp2[5];
    FILE *ifp;
    FILE *ofp;
    int i;

    ofp = fopen(filename, "wb");
    if (ofp != 0)
    {
        if (fwrite(emp1, sizeof(emp1), 1, ofp) != 1)
        {
            fprintf(stderr, "Failed to write to %s\n", filename);
            exit(1);
        }
        fclose(ofp);
    }

    ifp = fopen(filename, "rb");
    if (ifp != 0)
    {
        if (fread(emp2, sizeof(emp2), 1, ifp) != 1)
        {
            fprintf(stderr, "Failed to read from %s\n", filename);
            exit(1);
        }
        fclose(ifp);
    }

    for (i = 0; i < 5; i++)
    {
        if (emp1[i].age != emp2[i].age ||
            emp1[i].salary != emp2[i].salary ||
            strcmp(emp1[i].name, emp2[i].name) != 0 ||
            strcmp(emp1[i].address, emp2[i].address) != 0)
            printf("Difference in record %d\n", i);
    }

    return 0;
}

文件内容sampledata.bin

0x0000: 59 6F 64 61 00 00 00 00 00 00 00 00 00 00 00 00   Yoda............
0x0010: 17 00 00 00 C8 AF 00 00 41 73 69 61 00 00 00 00   ........Asia....
0x0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x0030: 00 00 00 00 00 00 00 00 44 61 72 74 68 00 00 00   ........Darth...
0x0040: 00 00 00 00 00 00 00 00 22 00 00 00 28 09 00 00   ........"...(...
0x0050: 4E 20 41 6D 65 72 69 63 61 00 00 00 00 00 00 00   N America.......
0x0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x0070: 4A 61 62 62 61 00 00 00 00 00 00 00 00 00 00 00   Jabba...........
0x0080: 16 00 00 00 BE 15 00 00 41 66 72 69 63 61 00 00   ........Africa..
0x0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00A0: 00 00 00 00 00 00 00 00 4C 75 6B 65 00 00 00 00   ........Luke....
0x00B0: 00 00 00 00 00 00 00 00 21 00 00 00 47 0D 00 00   ........!...G...
0x00C0: 53 20 41 6D 65 72 69 63 61 00 00 00 00 00 00 00   S America.......
0x00D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00E0: 4C 65 69 61 00 00 00 00 00 00 00 00 00 00 00 00   Leia............
0x00F0: 2C 00 00 00 15 1A 00 00 45 75 72 6F 70 65 00 00   ,.......Europe..
0x0100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x0110: 00 00 00 00 00 00 00 00                           ........
0x0118:
于 2013-11-09T06:21:40.977 回答
2

你没有指定你的意思fwrite doesn't work,但我假设你在 Windows 上工作,在这种情况下你需要指定"wb"to fopen默认情况下,在 Windows 上,它写入text mode(ie "wt")。

于 2013-11-09T06:44:55.753 回答
1

struct按原样写入文件或套接字不是一个好主意。它邀请复杂来解决问题。最好的方法是在编写之前使用序列化。此外,正如 Jim 上面指出的,确保以二进制文件打开文件。

看看这个问题和答案。您的问题有一个很好的答案和解释。 通过 C 中的套接字传递结构

于 2013-11-09T07:11:10.310 回答
0

数据序列化是一项不平凡的任务。正如其他人指出的那样,在某些情况下,可以将结构的内容作为二进制数据写入磁盘。写起来最简单,但不太可能稳定。每次重新编译代码时,都可能会改变写入和读取数据的格式。

您最好的选择是使用标准数据交换格式,例如 CSV、XML 或 JSON。有许多现有工具可以利用这些格式,因此您应该考虑使用其中一种。

于 2013-11-09T15:26:09.470 回答