I am trying to read a binary file in C#, but I am facing a problem. I declared the following:
public static readonly UInt32 NUMBER = 0XCAFEBABE;
Then while reading from the very beginning of the file I am asking to read the first 4 bytes (already tried different ways, but this is the simplest):
UInt32 num = in_.ReadUInt32(); // in_ is a BinaryReader
While I have that the 4 bytes are CA, FE, BA and BE (in hex) while convert them to UInt
I am getting different values. NUMBER is 3405691582, num is 3199925962.
I also tried to do this:
byte[] f2 = {0xCA, 0xFE, 0xBA, 0xBE};
and the result of doing BitConverter.ToUInt32(new byte[]{0xCA, 0xFE, 0xBA, 0xBE},0)
is 3199925962.
can anyone help me?
This is because of the little endianness of your machine. See BitConverter.IsLittleEndian
property to check this.
Basically, numbers are stored in reverse byte order, compared to how you would write them down. We write the most significant number on the left, but the (little endian) PC stores the least significant byte on the left. Thus, the result you're getting is really 0xBEBAFECA
(3199925962 decimal) and not what you expected.
You can convert using bit shifting operations:
uint value = (f2[0] << 24) | (f2[1] << 16) | (f2[2] << 8) | f2[3];
There are many more ways to convert, including IPAddress.NetworkToHostOrder
as I4V pointed out, f2.Reverse()
, etc.
For your specific code, I believe this would be most practical:
uint num = (uint)IPAddress.NetworkToHostOrder(in_.ReadInt32());
This may result in an arithmetic underflow however, so it may cause problems with a /checked
compiler option or checked
keyword (neither are very common).
If you want to deal with these situations and get even cleaner code, wrap it in an extension method:
public static uint ReadUInt32NetworkOrder(this BinaryReader reader)
{
unchecked
{
return (uint)IPAddress.NetworkToHostOrder(reader.ReadInt32());
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With