2009-05-22 65 views
7

我想用BinaryReader類讀取二進制文件,並且需要將它作爲UInt32塊讀取,然後做一些位移等後綴。爲什麼BinaryReader.ReadUInt32()會顛倒位模式?

但是,由於某種原因,當我使用ReadUInt32方法時,位順序反轉。

如果我比如有一個文件,其中前四個字節看起來像這樣十六進制,0x12345678,他們最終就這樣被ReadUInt32讀取後:0x78563412

如果我使用的ReadBytes(4)方法中,我得到了預期的數組:

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

這是爲什麼?它只是方式.net代表內存中的提示?在不同的平臺上(我正在運行64位Windows 7,.net 3.5 SP1)是否一樣?

+0

您是否可以通過告訴我們如何修復它來平息我們的好奇心? :) – 2009-05-23 02:06:12

+1

當然:)實際上,字節順序的方式並不重要,只要它跨平臺(x64,x86)是一致的,我仍然可以提取我需要的位,我只需要更改我的位移動。據我所知,uint通常存儲爲little-endian,而不僅僅是ReadUInt32的uint構建,因此可以使一切變得更加簡單。 – 2009-05-23 08:27:08

回答

8

這似乎是一個endianness問題。 The docs說ReadUint32讀小端,所以第一個字節是最不重要的,所以它進入最低的內存位置。你的作家必須是大前鋒?

BinaryWriter.Write(UInt32)says it writes也是小端。你的二進制數據源不是BinaryWriter嗎?

基本上你需要做的,解決它,這是什麼:

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

這把最低顯著字節達24位,第2 LSB了8位,第3個LSB下8位,第4個LSB(MSB)下降24位。這樣做在幾個圖書館中都有涉及。

也許使用BitConverter會多一點明確:

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

是的,這與您的計算機硬件如何在內存中存儲提示有關。它可以在不同的平臺上有所不同,儘管大多數臺式電腦應該是相同的。

這就是所謂的字節順序 - 維基百科看到這裏:

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

1

這是平臺Endianess的問題。當你從一個流中讀取數據時,你必須相應地讀取它所寫的字節。如果您在.Net中創建數據,那麼.Net將正確讀取它。

0

Generic BinaryReader and BinaryWriter Extensions,一個偉大的方式來處理通用鑄造的非託管的方式。

對於VB。NET(只有安全的代碼,也可以在C#實現)使用以下命令:

進口System.IO 進口System.Runtime.CompilerServices 進口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 

現在,您可以實現BitConverter的相同功能,BinaryWriter

相關問題