C# - 将uint转换为byte[]

14

我使用BitConverter.GetBytes()将uint32转换为byte[],但是数组中的顺序似乎是相反的。 http://msdn.microsoft.com/en-us/library/1184xdy4.aspx (显示其字节数组似乎是小端)。

除了使用 LINQ 反转字节数组外,是否有更好的处理方式?


我想这就是我困惑的地方,因为BitConverter.IsLittleEndian返回false,但BitConverter.GetBytes()返回小端数组。 - Joel Barsotti
如果这是Windows系统,BitConverter.IsLittleEndian返回false显然是一个bug,因为x86和x86-64处理器都是小端字节序。 - Powerlord
5个回答

7

Array.Reverse 可以改变字节序。


6
如果您将在不同平台体系结构之间移动,简单地反转数组可能在一个平台上是正确的,但在已经使用大端序的平台上可能会失败。
您可以使用IPAddress.HostToNetworkOrder函数,它将确保数据始终按网络顺序(大端序)排列。
uint number = 234234233;
uint bigEndian = (uint)IPAddress.HostToNetworkOrder((int)number);
byte[] b = BitConverter.GetBytes(bigEndian);

谢谢。这比Array.Reverse更快。但是如果我不像这样编写代码,我会遇到类型问题:var buffer = BitConverter.GetBytes((uint)IPAddress.HostToNetworkOrder((int)i)); - Geograph
@Geograph,你遇到了什么问题?也许值得为此创建一个专门的问题,这样你就可以提供更完整的示例和细节。 - Chris Taylor
您的原始示例无法编译,出现错误“CS0266 无法隐式将类型 'long' 转换为 'uint'。存在显式转换(是否缺少强制转换?)” - Geograph
@Geograph,我明白了。是的,为了使其正常工作,您需要将数字转换为int,以获得int大小的结果。我会更新示例,谢谢。 - Chris Taylor

5

微软在BitConverter的文档页面上讨论了使用GetBytes()方法时的小端/大端问题。


3
我发现我困惑的一个重要原因是与此有关:IsLittleEndian字段报告为false,但它一定是小端序? 我的解决方法是用一个额外的参数来指定字节顺序包装所有BitConverter调用,然后添加一个函数来检查是否需要反转字节。
public static class BitEndianConverter
{
    public static byte[] GetBytes(bool value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }

    public static byte[] GetBytes(char value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }
    public static byte[] GetBytes(double value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }
    public static byte[] GetBytes(float value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }
    public static byte[] GetBytes(int value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }
    public static byte[] GetBytes(long value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }
    public static byte[] GetBytes(short value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }
    public static byte[] GetBytes(uint value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }
    public static byte[] GetBytes(ulong value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }
    public static byte[] GetBytes(ushort value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }

    private static byte[] ReverseAsNeeded(byte[] bytes, bool wantsLittleEndian)
    {
        if (wantsLittleEndian == BitConverter.IsLittleEndian)
            return bytes;
        else
            return (byte[])bytes.Reverse().ToArray();
    }
}

我复制了这个类,它运行良好,比其他解决方案更直观和易读。我想知道是否有意义或者是否可能将 GetBytes 设为通用的?例如:public static byte[] GetBytes<T>(T value, bool littleEndian)... - shelbypereira

1
以下是一个快速获得大端字节数组的方法。
    public static byte[] GetBigEndianBytes(UInt32 val, bool isLittleEndian)
    {
        UInt32 bigEndian = val;
        if (isLittleEndian)
        {
            bigEndian = (val & 0x000000FFU) << 24 | (val & 0x0000FF00U) << 8 |
                 (val & 0x00FF0000U) >> 8 | (val & 0xFF000000U) >> 24;
        }
        return BitConverter.GetBytes(bigEndian);
    }

这种重载可能很方便,但在使用不同字节序的机器时必须小心。

    public static byte[] GetBigEndianBytes(UInt32 val)
    {
        return GetBigEndianBytes(val, BitConverter.IsLittleEndian);
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接