.net 整数到字节数组

yqlxgs2m  于 2022-12-30  发布在  .NET
关注(0)|答案(6)|浏览(153)

我以为.net有某种简单的转换方法可以用来将int转换成字节数组呢?我做了一个快速搜索,所有的解决方案都是位屏蔽/一次移位一个字节,就像“美好的旧日子”。难道某个地方没有ToByteArray()方法吗?

mi7gmzs6

mi7gmzs61#

2020年的更新-BinaryPrimitives现在应该比BitConverter更受欢迎。它提供了特定于endian的API,并且分配性更低。

byte[] bytes = BitConverter.GetBytes(i);

不过也要注意,您 * 可能 * 希望检查BitConverter.IsLittleEndian,以查看它将以哪种方式出现!
注意,如果你重复地这样做,你可能想通过移位操作(>>/<<)或者使用unsafe代码来避免所有那些短暂的数组分配。移位操作还有一个优点,那就是它们不受平台字节序的影响;你 * 总是 * 按照你期望的顺序得到字节。

goqiplq2

goqiplq22#

Marc的答案当然是正确的。但是既然他提到了移位操作符和不安全代码作为替代方案。我想分享一个不太常见的替代方案。使用Explicit布局的结构体。这在原理上类似于C/C++ union
这是一个可以用来获取Int 32数据类型的组成字节的结构体的例子,它的好处是它是双向的,你可以操作字节值,并查看对Int 32数据类型的影响。

using System.Runtime.InteropServices;

  [StructLayout(LayoutKind.Explicit)]
  struct Int32Converter
  {
    [FieldOffset(0)] public int Value;
    [FieldOffset(0)] public byte Byte1;
    [FieldOffset(1)] public byte Byte2;
    [FieldOffset(2)] public byte Byte3;
    [FieldOffset(3)] public byte Byte4;

    public Int32Converter(int value)
    {
      Byte1 = Byte2 = Byte3 = Byte4 = 0;
      Value = value;
    }

    public static implicit operator Int32(Int32Converter value)
    {
      return value.Value;
    }

    public static implicit operator Int32Converter(int value)
    {
      return new Int32Converter(value);
    }
  }

现在可以按如下方式使用上述内容

Int32Converter i32 = 256;
 Console.WriteLine(i32.Byte1);
 Console.WriteLine(i32.Byte2);
 Console.WriteLine(i32.Byte3);
 Console.WriteLine(i32.Byte4);

 i32.Byte2 = 2;
 Console.WriteLine(i32.Value);

当然,不变性警察可能不会对最后一种可能性感到兴奋:)

avkwfej4

avkwfej43#

这可能是OT,但是如果你要序列化大量的原语类型或POD结构,Google Protocol Buffers for .Net可能会对你有用,它解决了上面@Marc提出的字节序问题,以及其他有用的特性。

u59ebvdq

u59ebvdq4#

"如果你是从谷歌来的"
对于一个老问题的另一个答案是John Skeet的Library,它提供了一些工具,可以让你直接将原始数据类型写入一个带有索引偏移量的byte[]中,如果你需要性能的话,它比BitConverter好得多。
Older thread discussing this issue here
John Skeet's Libraries are here
只需下载源代码并查看MiscUtil.Conversion名称空间。EndianBitConverter.cs会为您处理一切。

ijnw1ujt

ijnw1ujt5#

使用MemoryMarshalSpan释放堆分配

int messageLen = 1111;
Span<byte> messageTypeBytes = MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan(ref messageLen, 1));

基准点网

|            Method |      Mean |     Error |    StdDev | Allocated |
|------------------ |----------:|----------:|----------:|----------:|
| MemoryMarshalTest | 0.0023 ns | 0.0017 ns | 0.0014 ns |         - |
ktecyv1j

ktecyv1j6#

这里的大多数答案不是“不安全”就是不是LittleEndian安全。BitConverter不是LittleEndian安全的。因此,基于here中的一个示例(参见PZahra的帖子),我创建了一个LittleEndian安全版本,方法是在BitConverter.IsLittleEndian == true时反向阅读字节数组

void Main(){    
    Console.WriteLine(BitConverter.IsLittleEndian); 
    byte[] bytes = BitConverter.GetBytes(0xdcbaabcdfffe1608);
    //Console.WriteLine(bytes); 
    string hexStr = ByteArrayToHex(bytes);
    Console.WriteLine(hexStr);
}

public static string ByteArrayToHex(byte[] data) 
{ 
   char[] c = new char[data.Length * 2]; 
   byte b; 
  if(BitConverter.IsLittleEndian)
  {
        //read the byte array in reverse
        for (int y = data.Length -1, x = 0; y >= 0; --y, ++x) 
        { 
            b = ((byte)(data[y] >> 4)); 
            c[x] = (char)(b > 9 ? b + 0x37 : b + 0x30); 
            b = ((byte)(data[y] & 0xF)); 
            c[++x] = (char)(b > 9 ? b + 0x37 : b + 0x30); 
        }               
    }
    else
    {
        for (int y = 0, x = 0; y < data.Length; ++y, ++x) 
        { 
            b = ((byte)(data[y] >> 4)); 
            c[x] = (char)(b > 9 ? b + 0x37 : b + 0x30); 
            b = ((byte)(data[y] & 0xF)); 
            c[++x] = (char)(b > 9 ? b + 0x37 : b + 0x30); 
        }
    }
    return String.Concat("0x",new string(c));
}

它返回以下内容:

True
0xDCBAABCDFFFE1608

这就是进入字节数组的十六进制数。

相关问题