76

我认为.net 有某种简单的转换方法可用于将 int 转换为字节数组?我进行了快速搜索,所有解决方案都是一次位屏蔽/移动一个字节,例如“美好的时光”。某处没有 ToByteArray() 方法吗?

4

5 回答 5

129

2020 年的更新 -BinaryPrimitives现在应该优先于BitConverter. 它提供特定于字节序的 API,并且分配较少。


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

尽管还请注意,您可能需要检查BitConverter.IsLittleEndian以查看将出现的方式!

请注意,如果您重复>>执行此操作,您可能希望通过移位操作 ( / <<) 或使用unsafe代码自己编写来避免所有这些短暂的数组分配。移位操作具有不受平台字节序影响的优点;你总是按照你期望的顺序得到字节。

于 2010-11-14T08:01:14.187 回答
40

马克的答案当然是正确的答案。但是由于他提到了移位运算符和不安全的代码作为替代方案。我想分享一个不太常见的替代方案。使用带有Explicit布局的结构。这在原理上类似于 C/C++ union

这是一个结构示例,可用于获取 Int32 数据类型的组成字节,好处是它有两种方式,您可以操作字节值并查看对 Int 的影响。

  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);

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

于 2010-11-14T08:34:35.787 回答
2

这可能是 OT,但如果您要序列化许多原始类型或 POD 结构,Google Protocol Buffers for .Net可能对您有用。这解决了上面提到的@Marc 的字节顺序问题,以及其他有用的功能。

于 2010-11-14T13:44:55.167 回答
2

如果您从 Google 来到这里

对一个较旧问题的替代答案是指 John Skeet 的库,该库具有可让您将原始数据类型直接写入具有索引偏移量的 byte[] 的工具。BitConverter比你需要性能要好得多。

在这里讨论这个问题的旧线程

约翰斯基特的图书馆在这里

只需下载源代码并查看MiscUtil.Conversion名称空间。 EndianBitConverter.cs为您处理一切。

于 2018-03-15T17:56:55.077 回答
0

这里的大多数答案要么是“不安全”,要么不是 LittleEndian 安全的。BitConverter 不是 LittleEndian 安全的。因此,在这里建立一个示例(请参阅 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

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

于 2014-11-11T02:13:54.077 回答