我正在尝试用C#读取二进制文件,但我遇到了问题。 我宣布了以下内容:
public static readonly UInt32 NUMBER = 0XCAFEBABE;
然后在从文件的最开头读取时我要求读取前4个字节(已尝试过不同的方法,但这是最简单的):
UInt32 num = in_.ReadUInt32(); // in_ is a BinaryReader
虽然我有4个字节是CA,FE,BA和BE(十六进制),同时将它们转换为UInt
我得到不同的值。 NUMBER是3405691582,num是3199925962。
我也尝试过这样做:
byte[] f2 = {0xCA, 0xFE, 0xBA, 0xBE};
,执行BitConverter.ToUInt32(new byte[]{0xCA, 0xFE, 0xBA, 0xBE},0)
的结果是3199925962。
任何人都可以帮助我吗?
感谢
答案 0 :(得分:7)
这是因为你机器的endianness很小。请参阅BitConverter.IsLittleEndian
属性进行检查。
基本上,数字以反向字节顺序存储,与将它们写下来的方式相比较。我们在左边写了最重要的数字,但是(小端)PC在左边存储最小有效字节。因此,您获得的结果实际上是0xBEBAFECA
(十进制3199925962)而不是您的预期。
您可以使用位移操作进行转换:
uint value = (f2[0] << 24) | (f2[1] << 16) | (f2[2] << 8) | f2[3];
还有很多方法可以转换,包括IPAddress.NetworkToHostOrder
,正如I4V指出的那样,f2.Reverse()
等等。
对于您的具体代码,我认为这是最实用的:
uint num = (uint)IPAddress.NetworkToHostOrder(in_.ReadInt32());
然而,这可能会导致算术下溢,因此可能会导致/checked
compiler option or checked
keyword出现问题(两者都不常见)。
如果您想处理这些情况并获得更清晰的代码,请将其包装在扩展方法中:
public static uint ReadUInt32NetworkOrder(this BinaryReader reader)
{
unchecked
{
return (uint)IPAddress.NetworkToHostOrder(reader.ReadInt32());
}
}
答案 1 :(得分:3)
这就是所谓的byte order:
var result1 = BitConverter.ToUInt32(new byte[] { 0xCA, 0xFE, 0xBA, 0xBE }, 0);
//3199925962
var result2 = BitConverter.ToUInt32(new byte[] { 0xBE, 0xBA, 0xFE, 0xCA }, 0);
//3405691582