10

我正在尝试用 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。

谁能帮我?

4

2 回答 2

9

这是因为您的机器的小字节序。请参阅BitConverter.IsLittleEndian属性以检查这一点。

基本上,与您将它们写下来的方式相比,数字是以相反的字节顺序存储的。我们将最重要的数字写在左边,但(小端序)PC 将不重要的字节存储在左边。因此,您得到的结果实际上是0xBEBAFECA(3199925962 十进制),而不是您所期望的。

您可以使用位移操作进行转换:

uint value = (f2[0] << 24) | (f2[1] << 16) | (f2[2] << 8) | f2[3];

还有更多的转换方式,包括IPAddress.NetworkToHostOrderI4V 指出的f2.Reverse(),等等。

对于您的特定代码,我相信这将是最实用的:

uint num = (uint)IPAddress.NetworkToHostOrder(in_.ReadInt32());

然而,这可能会导致算术下溢,因此可能会导致/checked编译器选项或checked关键字出现问题(两者都不是很常见)。

如果您想处理这些情况并获得更简洁的代码,请将其包装在扩展方法中:

public static uint ReadUInt32NetworkOrder(this BinaryReader reader)
{
    unchecked
    {
        return (uint)IPAddress.NetworkToHostOrder(reader.ReadInt32());    
    }
}
于 2013-04-19T10:47:19.480 回答
4

这就是所谓的字节顺序

var result1 = BitConverter.ToUInt32(new byte[] { 0xCA, 0xFE, 0xBA, 0xBE }, 0);
//3199925962

var result2 = BitConverter.ToUInt32(new byte[] { 0xBE, 0xBA, 0xFE, 0xCA }, 0);
//3405691582
于 2013-04-19T10:48:19.617 回答