When reading and writing binary-format files, my preference is to define sets of "get" and "put" functions, like this:
/* read a 4-byte little-endian integer */
int32_t get32(FILE *fp)
{
int32_t ret = 0;
ret |= getc(fp);
ret |= getc(fp) << 8;
ret |= (uint32_t)getc(fp) << 16;
ret |= (uint32_t)getc(fp) << 24;
return ret;
}
/* write a 4-byte little-endian integer */
void put32(int32_t val, FILE *fp)
{
putc( val & 0xff, fp);
putc((val >> 8) & 0xff, fp);
putc((val >> 16) & 0xff, fp);
putc((val >> 24) & 0xff, fp);
}
Then instead of your fwrite(&u32, 4, 1, file)
, I'd call put32(u32, file)
.
This is, admittedly, not that much more convenient than fwrite
, but it gives precise control over byte order, which is the other big issue when it comes to reading/writing binary data files.
Also, getting these "get" and "put" routines absolutely right can be a little tricky. The simplified versions I've shown aren't perfect, as they play a little fast-and-loose with signed/unsigned distinctions, and the get32
I've shown doesn't have any EOF handling.
Typing in all the get's and put's can indeed be a nuisance, but in my experience it's actually a lot less of a nuisance, in the end, than some of the allegedly "more convenient" techniques people try to use. For example, rather than reading and writing one variable at a time, it's quite popular to put all your variables into a structure and then read and write whole instances of that structure — but then you get to spend many, many hours on the joyless task of trying to manage your structure padding and alignment.
If you truly have so many of these to read and write that manually maintaining the get's and put's is unworkable, I'd say it's time to look into some kind of interface generator to write the serialization and deserialization code for you, based on a nice, high-level description of your data file format and your mapping of data file fields to variable or member names in your code.
wrongantipreferable, because you're saying, "if the size of this variable changes, I want the file format to silently change". But I do *not* want the file format to silently change. Ever. – Steve Summit Feb 08 '23 at 23:57