Reputation: 43
For my first question here, I'd like to talk about reading binary files in C++; I'm recoding an ID3 tag library.
I'm parsing the header which is a binary file, the first 10bytes are as follow:
ID3 = 3 bytes = constant identifier
0xXXXX = 2 bytes = version (MSB: major version, LSB: minor. eg: 0x0301 = v3.1)
0xXX = 1 byte = some flags
4*0xXX = 4 bytes = size
here's the piece of code to process that :
char id[4];
uint16_t version;
uint8_t flags;
uint32_t size;
std::ifstream _stream;
_stream = std::ifstream(_filename, std::fstream::binary);
_stream.read(id, 3);
id[3] = 0;
// process id
_stream.read((char *)&version, 2);
// process version
_stream.read((char *)&flags, 1);
// process flags
_stream.read((char* )&size, 4);
// process flags
_stream.close();
everything works fine except for version. lets say it's v3.0 (0x0300), the value set in version is 0x03, I would understand this behavior in text mode as it would consider 0x00 as end of string but here I'm reading in binary. And use numeric formats.
Other strange thing, if I process it in 2 times I can make it work, eg :
uint16_t version = 0;
char buff;
_stream.read(&buff, 1);
version = (buff << 8);
_stream.read(&buff, 1);
version |= buff;
In this case the value of version is 0x0300.
Do you have any idea why the first method doesn't work properly? Am I doing something wrong ?
Anyways, thanks for your help,
Cheers !
Upvotes: 4
Views: 318
Reputation: 52337
The version field consists not of an unsigned short but of two unsigned bytes (major version, minor version). You should read the two version numbers separately to not getting mangled up in endianess problems.
Endianess is platform-specific. If you insist on reading a single short that combines major and minor version, you could work around it. But in the end you write less clean and understandable code to solve a problem you created yourself.
Upvotes: 4
Reputation: 8501
This seems like an endianess issue. So what is it? According to Wikipedia:
Endianness refers to the sequential order in which bytes are arranged into larger numerical values, when stored in computer memory or secondary storage
Visual example of a layout in memory:
When you read the value as a one-shot, the bytes get re-arranged, probably because of an inconsistency between the way they were written and the way they are read.
Since you know the order in which they lay in memory, you should do one of the following:
_byteswap_ushort
in VC++ or __builtin_bswap16
for GCCUpvotes: 1