2

I have tried to look this up in multiple places and I cannot understand why fwrite doesn't work.

If I had a structure with 100 fields I would not want to use fprintf with 100 format specifiers.

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();
 }
CP3O
  • 429
  • 1
  • 6
  • 21

4 Answers4

3

There are two answers:

  1. It does work, if everything is set correctly and porting the written data to other machines is not an issue.
  2. It doesn't work if you have any of a large number of common features in data structures, or if you need to move the data from one type of machine (say an Intel machine) to another type (say PowerPC or SPARC).

In your example structure, you have no pointers, so you could write the structure verbatim to a file, and then in another invocation of the program running on the same (type of) machine, you could read it back in, and you would see the same data.

However, if your structure contained pointers, you could not meaningfully write the structure to disk. The pointers in one invocation of the program need not have any significance in another invocation of the program. If you needed to port the data between a little-endian (Intel) and big-endian (PowerPC, SPARC) machine, you'd have to use a platform-neutral way of accessing the data; simply writing the data to disk would not work.


So, where portability is not an issue, this code should work — Unix or Windows. It uses the "wb" and "rb" arguments to fopen() because the data is binary data, not plain text. The b is optional but harmless on Unix; it is crucial on Windows. The code also fixes the file name to sampledata.bin so it can be run on either platform, writing in the current directory. It writes the data; it then reads the data; it then compares the read data with the written data, reporting any problems. If the program says nothing, all is OK.

#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;
}

Content of the file 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:
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
2

You don't specify what you mean by fwrite doesn't work, but I'll assume you're working on Windows, in which case you need to specify "wb" to fopen. By default on Windows, it's writing in text mode (i.e. "wt").

Jim Buck
  • 20,482
  • 11
  • 57
  • 74
1

not a good idea to write struct to file or sockets as it is. It is inviting complex to solve problems. the best approach is to use serialization before writing. Also, as Jim pointed out above, make sure to open the file in binary.

Take a look in this question and the answers. there is a pretty good answer and explanation for your question. Passing a structure through Sockets in C

Community
  • 1
  • 1
joe
  • 1,136
  • 9
  • 17
0

Data serialization is a non-trivial task. As some others have pointed out, it is possible in some cases to write the contents of your struct to disk as binary data. It's the simplest to write, but it is unlikely to be stable. Each time you recompile your code, it can potentially change the format the data is written and read in.

Your best option is to use a standard data interchange format, such as CSV, XML, or JSON. There are many existing tools to utilize these formats, so you should look into using one of them.

Holly
  • 5,270
  • 1
  • 24
  • 27