将十六进制数转换为c#的int值不正确

本文关键字:int 不正确 十六进制数 转换 | 更新日期: 2023-09-27 18:09:55

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

有人能帮我吗?

将十六进制数转换为c#的int值不正确

这是因为您的机器的端序性很小。查看BitConverter.IsLittleEndian属性检查

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

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

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

还有更多的转换方法,包括I4V指出的IPAddress.NetworkToHostOrder, 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());    
    }
}

这就是所谓的字节顺序:

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