為什麼 BinaryReader.ReadUInt32() 反轉位模式? (Why does BinaryReader.ReadUInt32() reverse the bit pattern?)


問題描述

為什麼 BinaryReader.ReadUInt32() 反轉位模式? (Why does BinaryReader.ReadUInt32() reverse the bit pattern?)

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

But, for some reason bit order is reversed when I use the ReadUInt32 method.

If I for example have a file where the first four bytes looks like this in hex, 0x12345678, they end up like this after being read by ReadUInt32: 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 it just the way .net represents uints in memory? Is it the same across the different platforms (I am running 64bit Windows 7, .net 3.5 sp1)?

‑‑‑‑‑

參考解法

方法 1:

Yes, this has to do with how your computer hardware stores uints in memory.  It can be different across different platforms, although most desktop computers should be the same.

This is called endianness ‑‑ see wikipedia here:

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

方法 2:

This seems to be an endianness issue.  The docs say ReadUint32 reads in little‑endian so the first byte is the least‑significant so it goes to the lowest memory location.  Your writer must be big‑endian?

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

Essentially what you need to do to fix it is this:

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

This shifts the least‑significant byte up 24 bits, the 2nd LSB up 8 bits, the 3rd LSB down 8 bits, and the 4th LSB (the MSB) down 24 bits.  Doing this is covered in several libraries.

Perhaps using BitConverter would be a bit more clear:

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);

方法 3:

Look into Jon Skeet's MiscUtil library for the Endian* classes, like EndianBinaryReader and EndianBitConverter.

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

方法 4:

Jon Skeet's written a BitConverter with configurable endian‑ness.  You might find it useful.

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

方法 5:

This is an issue of platform Endianess. When you read data from a stream you must read it accordingly to the endianess it was written as. If you created the data in .Net, then .Net will read it correctly. 

(by Egil HansenClydeColin BurnettbsneezeMichael PetrottaRemus Rusanu)

參考文件

  1. Why does BinaryReader.ReadUInt32() reverse the bit pattern? (CC BY‑SA 3.0/4.0)

#32-bit #64-bit #bit-manipulation #Endianness #.net






相關問題

內聯彙編 - cdecl 和準備堆棧 (Inline assembly - cdecl and preparing the stack)

來自 32 位用戶代碼的 64 位系統中的 ioctl 命令錯誤 (ioctl command wrong in 64 bit system from 32 bit user code)

Baiklah, PR: Bagaimana mungkin X[i] diinterpretasikan sama dengan i[X] di C? (Alright, homework: How can X[i] possibly be interpretted the same as i[X] in C?)

x32 ABI - гэта інструмент, як ім карыстацца (x32 ABI is this a tool ,how to use this)

Biên dịch Visual Studio 2012 32bit trên hệ thống 64bit (Visual Studio 2012 32bit compilation on 64bit system)

如何讓 Netbeans 7.2 使用 32 位 JVM (How get Netbeans 7.2 to use 32 Bit JVM)

反彙編代碼中的數組聲明 (Declaration of an array in disassembled code)

用C編寫跨平台應用程序 (Writing cross-platform apps in C)

為什麼 BinaryReader.ReadUInt32() 反轉位模式? (Why does BinaryReader.ReadUInt32() reverse the bit pattern?)

32 位 RHEL 機器上的內存使用 (Memory use on 32 bit RHEL machine)

將 32 位應用程序安裝到 C:\Program Files\ 而不是 C:\Program Files(x86)\ 會有什麼負面影響? (What would be the negative effects of installing a 32bit app into the C:\Program Files\ instead of the C:\Program Files(x86)\?)

Arduino 將浮點數轉換為十六進制 IEEE754 單精度 32 位 (Arduino convert float to hex IEEE754 Single precision 32-bit)







留言討論