I have some ancient c code that reads files stored in raw binary
format. The first 216 bytes are to be read into an instance of:
struct Sheader
{
long attr_start;
long form_start;
short fsize;
short attr_size;
short lastfieldidx;
short num_inputs;
char oldheader[200];
};
The way the C code does this is by fread ((void *)header, sizeof
(struct Sheader), 1, file); Is there a better way to do this in C++?
You have to parse the data in the file into the struct; for that you
have many alternatives. Reading from the file byte-by-byte is rubbish
and not recommended. Allocate the buffer which is size of the header:
char* buffer = new char[216];
Then fill the buffer with block read. fread works just fine. Or, if
you have a framework to use which has memory mapped I/O, even better:
just lock the region of the file (the first 216 bytes?) and use the
acquired pointer to the mapped region.
Either way, you will end up having a pointer:
char* buffer; // points to the 216 bytes of header data
Then you parse the data. It's useful to create few helper functions
for the parsing, example:
long read_long(char*& p)
{
long value = p[0] | (p[1] << 8) | (p[2] << 16) | p[3] << 24);
p += 4;
return value;
}
Something like that. If you encapsulate the parser into a class, you
don't need to pass the pointer around (you will still be passing
instance of the parser; "this" pointer around but that's another
story).
Also, depending on the endianess of the file you might want to modify
the byte-order in above read_long function (/method).
That's the main gist of it pretty much. I use parser class like that
in all the code I wrote when dealing with binary objects. The
constructor takes pointer to the data and size (for overflow checking
purposes and such) and then just parse away! Main point is to just
dead with the data as region of memory, this way works nicely even
with game consoles like XBOX and PS3, old and new operating systems,
etc. I advocate this as the "best" approach, forget diddling about
with the C++ streams - sure feel free to use them to initialize the
pointer for the parser but it's not really the critical detail.
This is simple, efficient, portable .. there really is no downside. If
you however, read from file, parse, read from file, parse and repeat..
the code isn't any simpler to write but the performance will suck
eventually. If you pick up bad habits, you'll stick with them as they
grow into you - that's bad.
This isn't premature optimization in case someone suggests that. This
is just good practice. Have a nice day.