Hello,

I am trying to read exact 2 bytes from binary file, and transfer it to int, whatever is it 2 or 4 bytes. Atm on my computer is 4 bytes. So I have two bytes into four bytes scenario. I am using this code

ifstream in_stream;
in_stream.open("test.dat", ios::binary);
streamoff offset = 0x4E00; 
in_stream.seekg(offset);

int number1;
char buffer[2];
in_stream.read((char*)&buffer, 2);
number1= buffer[0]+ (buffer[1]<<8);
cout << number1 <<endl;

in_stream.seekg(offset);
short number2;
in_stream.read((char *)&number2, 2);
cout << number2;

but I can't get it why I get different number2 and number1 output? Not on every input are they different, but on some they are, and I can't notice pattern on which they are different. Any hints, help? Thanks in advance

>>line 9: number1= buffer[0]+ (buffer[1]<<8);

Try this: number = *(short *)buffer; This assume sizeof(short) = 2 on your computer. There is no guarentee that is true on every computer.

That may not work either if the binary file was written in little endian format and you are attempting to read it on a machine with big endian format. More info about that in this wiki article

Edited 5 Years Ago by Ancient Dragon: n/a

Although Ancient Dragon's solution should work, the problem with your original code is probably with the byte order. Most modern computers have little endian byte orders meaning that the bytes are stored least significant to most significant, e.g. a 16-bit integer of 0x1234 would be stored as the 8-bit bytes 0x34,0x12. You read the bytes with a big endian byte order, which is most significant to least significant. Basically, you need to flip the subscripts on line 9.

Thanks Ancient Dragon, your solution works, but I do not want to assume size of short, tho as far as I know short can't be shorter then 2 bytes.

Program should work on all systems, only thing I am sure is that I am reading 2 byte integers. I want to make as much as possible general purpose program for that problem.

@Chris, I tried fliping subscripts, but then I get some wild number, so I think, at least on my machine I used good endian. But, how can I know when to use which endian? I do not know how my file will be written.

thanks for fast reply people.

>>Most modern computers have little endian byte orders

No. MS-Windows and *nix are both different, and both modern operating systems.

>>Program should work on all systems, only thing I am sure is that I am reading 2 byte integers

Your program is going to have to be a bit smarter than just blindly assuming a certain byte order. The program will have to figure out which byte order is being used on the os and act accordingly so that it can read the binary data file correctly.

MS-Windows and *nix are both different

Huh? I thought endianness is HW-dependent, not OS-dependent.

e.g.:
Intel: little endian
Motorola: high endian

Huh? I thought endianness is HW-dependent, not OS-dependent.

That's true at the OS vs. CPU level, but it's more of a practicality than a requirement. While the processor runs in a specific endian mode (some can even switch between modes), endianness at any higher level is really about performance and portability. Windows, for example, could run in big-endian mode on an x86 processor, but that would require OS level re-ording of bytes since the x86 family is strictly little-endian. For performance reasons, failing to match the endianness of the hardware is stupid.

At a higher level, file formats vary between little-endian (eg. BMP), big-endian (eg. JPEG), and variable-endian (eg. TIFF), all on the same hardware and OS. As long as programs properly process those formats in the correct order, the endianness of the OS and underlying hardware is irrelevant.

Edited 5 Years Ago by Narue: n/a

Hello,

I am trying to read exact 2 bytes from binary file, and transfer it to int, whatever is it 2 or 4 bytes. Atm on my computer is 4 bytes. So I have two bytes into four bytes scenario. I am using this code

ifstream in_stream;
in_stream.open("test.dat", ios::binary);
streamoff offset = 0x4E00; 
in_stream.seekg(offset);

int number1;
[B]unsigned [/B]char buffer[2];
in_stream.read((char*)&buffer, 2);
number1= buffer[0]+ (buffer[1]<<8);
cout << number1 <<endl;

in_stream.seekg(offset);
short number2;
in_stream.read((char *)&number2, 2);
cout << number2;

but I can't get it why I get different number2 and number1 output? Not on every input are they different, but on some they are, and I can't notice pattern on which they are different. Any hints, help? Thanks in advance

unsigned was missing, I really didn't saw that :(
Thank for helping. Regarding little or big endian, that can be solvable like this:

int i = 1;
char *pc = (char *)&i;
 
if ( *pc == 1 )
{
    /* little endian */
}
else
{
    /* Big endian */
}

so, I guess, thread solved, yay

Regarding little or big endian, that can be solvable like this:

No it can't. The code you posted will work on all computers regardless of endianess.

yes, my code will work, but I posted for people who need to know if they are working on little or big endian computers, I think that code would do the trick, rite?

I think that code would do the trick, rite?

Assuming char and int have different sizes, yes.

This question has already been answered. Start a new discussion instead.