为什么BinaryReader.ReadUInt32()反转位模式?
-
23-08-2019 - |
题
我试图读取与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)?
解决方案
这似乎是一个字节序问题。 说ReadUint32在小端读取文档因此,第一个字节是最低显著如此这般以最低的内存位置。你的作家必须是大端?
BinaryWriter.Write(UInt32) href="http://msdn.microsoft.com/en-us/library/d79ecdwh.aspx" rel="noreferrer">说,写小端了。是您的二进制数据源没有的BinaryWriter?
从本质上讲,你需要做的,解决它是这样的:
uint a = 0x12345678;
uint b = ((a & 0x000000FF) << 24) + ((a & 0x0000FF00) << 8) + ((a & 0x00FF0000) >> 8) + ((a & 0xFF000000) >> 24);
此向上移动的至少-显著字节24个比特,第二LSB起来8位,第3向下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);
其他提示
是的,这与在内存中如何您的计算机硬件商店的uint做。它可以是在不同的平台不同,虽然大多数桌面计算机应是相同的。
此被称为字节序 - 见维基这里:
看到乔恩斯基特的MiscUtil库用于Endian的*类,像EndianBinaryReader和EndianBitConverter。
乔恩斯基特的书面具有可配置的字节序一BitConverter。您可能会发现它很有用。
这是平台字节序的问题。当你阅读从流数据则必须相应地念给它被写为字节顺序。如果你创建.NET中的数据,然后将净正确读取它。
通用BinaryReader在和的BinaryWriter扩展,一个伟大的方式来处理通用铸造非托管方式。
有关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
等