Why does BinaryReader.ReadUInt32 () reverse the bitmap?

I am trying to read a binary file with the BinaryReader class, and I need to read it as UInt32 blocks, and then do some bit shifts, etc. afterwords.

But for some reason, the order of the bits is canceled when I use the ReadUInt32 method.

If, for example, I have a file in which the first four bytes look like hexadecimal, 0x12345678 , they end as ReadUInt32 read: 0x78563412 .

If I use the ReadBytes (4) method, I get the expected array:

 [0x00000000] 0x12 byte [0x00000001] 0x34 byte [0x00000002] 0x56 byte [0x00000003] 0x78 byte 

Why is this? Is this just the way .net represents uints in memory? Is it the same thing on different platforms (am I running 64-bit Windows 7, .net 3.5 sp1)?

+7
bit-manipulation 64bit endianness 32-bit
source share
6 answers

This seems to be an endianness problem. The docs say that ReadUint32 reads in little-endian, so the first byte is the least significant, so it goes to the lowest memory location. Should your writer be big?

BinaryWriter.Write(UInt32) says it writes little-endian. Is your binary data source not a BinaryWriter?

Essentially what you need to do to fix this:

 uint a = 0x12345678; uint b = ((a & 0x000000FF) << 24) + ((a & 0x0000FF00) << 8) + ((a & 0x00FF0000) >> 8) + ((a & 0xFF000000) >> 24); 

This shifts the least significant bit to 24 bits, the second least significant bit of the least significant bit is 8 bits, the third least significant bit is 8 bits, and the fourth least significant bit (MSB) is up to 24 bits. This is done in several libraries.

Perhaps using BitConverter would be clearer:

 uint a = 0x12345678; byte[] bytes = BitConverter.GetBytes(a); // Swap byte order uint b = BitConverter.ToUInt32(new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] }, 0); 
+8
source share

Yes, this is due to the way your computer equipment stores uints in memory. It can be different on different platforms, although most desktop computers should be the same.

This is called endianness - see wikipedia here:

http://en.wikipedia.org/wiki/Endian

+8
source share

Take a look at the Jon Skeet MiscUtil library for Endian * classes such as EndianBinaryReader and EndianBitConverter.

http://www.yoda.arachsys.com/csharp/miscutil/

+2
source share

This is an Endianess platform issue. When you read data from a stream, you should read it according to the content that was written as. If you created the data in .Net, then .Net will read it correctly.

+1
source share

John Skeet wrote a custom content bit converter. You may find this helpful.

http://www.yoda.arachsys.com/csharp/miscutil/

+1
source share

Read the Generic BinaryReader and BinaryWriter Extensions , a great way to handle the general launch of an unmanaged way.

For VB.NET (only safe code can also be achieved in C #), use the following:

Imports System.IO Imports System.Runtime.CompilerServices Imports System.Runtime.InteropServices

 <HideModuleName()> Public Module BinaryReaderExtensions <Extension()> Public Function Read(Of T As Structure)(br As BinaryReader) As T Dim bytes = br.ReadBytes(Marshal.SizeOf(GetType(T))) Dim handle = GCHandle.Alloc(bytes, GCHandleType.Pinned) Return Marshal.PtrToStructure(handle.AddrOfPinnedObject, GetType(T)) End Function <Extension()> Public Function ReadReverse(Of T As Structure)(br As BinaryReader) As T Dim bytes = br.ReadBytes(Marshal.SizeOf(GetType(T))).Reverse.ToArray Dim handle = GCHandle.Alloc(bytes, GCHandleType.Pinned) Return Marshal.PtrToStructure(handle.AddrOfPinnedObject, GetType(T)) End Function End Module 

Now you can implement the same functionality for BitConverter , for BinaryWriter , etc.

0
source share

All Articles