I\'d like to save a struct in a file. I\'d like to realize a function which makes this work. I tried this code but it didn\'t work.
struct utilisateur //
Try this, and then if that's not doing what you want, try explaining how it differs from what you want.
void crea_fich(struct utilisateur *Tutilis)
{
FILE *f;
size_t nwritten;
f = fopen("futilis.dat","wb");
if (f == NULL)
{
fprintf(stderr, "Cannot open file for writing.\n");
exit(1);
}
nwritten = fwrite(Tutilis, sizeof Tutilis[0], 1, f);
fclose(f);
if (nwritten < 1)
{
fprintf(stderr, "Writing to file failed.\n");
exit(1);
}
}
No. You need to write out your data members individually, one at a time. You should not just blindly copy the memory representation of your struct into the file output buffer (which it is clear you are trying to do). Writing files that way will cause the files to non-portable (they won't be readable except on the platform that they were written), because of the endian-ness and the platform-specific padding of the struct elements.
Just a simple example :)
// your struct
struct Data
{
int first;
double second;
char third[10];
};
Then write the struct!
struct Data data = {22, 4.0, "Hi"};
FILE* output;
output = fopen("Data.dat", "wb");
fwrite(&data, sizeof(data), 1, output);
fclose(output);
Finally read the data from the file you created!
struct Data data;
FILE* input;
input = fopen("Data.dat", "rb");
fread(&data, sizeof(data), 1, input);
// you got the data from the file!
fclose(input);
Binary files are nightmares if not written and read wisely. You have to take care of a lot of things about the architecture where the file was created and where will it be read. Endianess and size of variables are the most important. Also, If you have pointers inside your struct
, the pointer that will be written to the file not the actual data where the pointer points to. Sorry, I didn't edit your code because it is full of compilation errors :)
I deleted my first answer because it was so wrong, sorry :)
Michael S is right; using fwrite
with a struct is wildly nonportable. But let's assume you don't care about that and you want something easy to write that will work.
The problem in your code is that you've broken the Golden Rule of sizeof
: never use sizeof
with a type name. Instead you should use sizeof
with an lvalue, and almost always with the dereference of another argument. Thus
Tutilis = malloc (sizeof (*Tutilis));
...
fwrite(Tutilis, sizeof (*Tutilis), 1, f);
If you follow this recipe it's much harder to get the size wrong.
I realize this is an old post, but it comes up when people search for this information, so I'll give my own solution.
This is basically what I have used in one of my games. I actually have some extra library specific code in my own function for dialogs, but this is essentially it. I write data individually. I don't think I have a struct for this data, but there is no difference, just write your individual struct members separately. As mentioned, it's better this way.
// returns 1 if successful, 0 if not
int savemap(const char *map_name)
{
FILE *file = NULL;
// open the file in write binary mode
file = fopen(map_name, "wb");
// always check return values to see if it was opened okay
if(file == NULL) {
fprintf(stderr, "Error opening file for writing.\n");
return 0;
}
// write file ID, version and pills
fwrite(MAP_ID, sizeof(char), strlen(MAP_ID)+1, file);
fwrite(&MAP_VER, sizeof(unsigned char), 1, file);
fwrite(&pills, sizeof(unsigned short), 1, file);
// write the map data (unsigned int map[315])
fwrite(&map, sizeof(unsigned int), 315, file);
// never forget to close the file
fclose(file);
return 1;
}
I'd look over the symbol names first, like NULL
and fprint
, not to mention that weird \0
. As an additional thought, you should close the file after writing to make sure it gets flushed to disk, and double check that futilis
variable is a char*
that contains a valid, writeable path.