我正在尝试使用BinaryReader类读取二进制文件,我需要将其作为UInt32的块读取,然后在后面进行一些位移等。
但是,由于某种原因,当我使用ReadUInt32方法时,位顺序会反转。
例如,如果我有一个文件,其中前四个字节在十六进制中显示为0x12345678
,则它们在被ReadUInt32读取后会以这样的结尾:0x78563412
。
如果我使用ReadBytes(4)方法,我会得到预期的数组:
[0x00000000] 0x12 byte
[0x00000001] 0x34 byte
[0x00000002] 0x56 byte
[0x00000003] 0x78 byte
这是为什么?这只是方式.net代表内存中的uint?在不同的平台上是否相同(我运行64位Windows 7,.net 3.5 sp1)?
答案 0 :(得分:8)
是的,这与您的计算机硬件如何将uint存储在内存中有关。虽然大多数台式计算机应该是相同的,但它可以在不同平台上有所不同。
这称为字节序 - 请在此处查看维基百科:
答案 1 :(得分:8)
这似乎是一个endianness问题。 The docs表示ReadUint32以little-endian读取,因此第一个字节是最不重要的,因此它会进入最低内存位置。你的作家必须是大头?
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位,第二LSB向上移位8位,第三LSB向下移位8位,第四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);
答案 2 :(得分:3)
查看Jon Skeet的Endis *类的MiscUtil库,如EndianBinaryReader和EndianBitConverter。
答案 3 :(得分:2)
Jon Skeet编写了一个带可配置字节序的BitConverter。您可能会发现它很有用。
答案 4 :(得分:1)
这是平台Endianess的问题。当您从流中读取数据时,必须根据其写入的字节顺序读取它。如果您在.Net中创建数据,那么.Net将正确读取它。
答案 5 :(得分:0)
阅读Generic BinaryReader and BinaryWriter Extensions,这是处理非托管方式的通用投射的好方法。
对于VB.NET(仅限安全代码,也可以在C#中实现)使用以下内容:
导入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
您现在可以为BitConverter
等BinaryWriter
等实现相同的功能。