Int 转字节数组

发布于 2024-10-01 20:23:04 字数 110 浏览 7 评论 0原文

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

I thought .net had some kind of easy conversion method to use for converting an int into a byte array? I did a quick search and all solutions are bit masking/shifting one byte at a time, like "the good ol days".
Is there not a ToByteArray() method somewhere?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

一抹微笑 2024-10-08 20:23:04

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


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

尽管还要注意,您可能想要检查BitConverter.IsLittleEndian以查看将出现哪种方式!

请注意,如果您重复执行此操作,您可能希望通过移位操作(>> / <<),或使用不安全代码。移位操作还有的优点是它们不受平台字节顺序的影响;您总是按照您期望的顺序获取字节。

Update for 2020 - BinaryPrimitives should now be preferred over BitConverter. It provides endian-specific APIs, and is less allocatey.


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

although note also that you might want to check BitConverter.IsLittleEndian to see which way around that is going to appear!

Note that if you are doing this repeatedly you might want to avoid all those short-lived array allocations by writing it yourself via either shift operations (>> / <<), or by using unsafe code. Shift operations also have the advantage that they aren't affected by your platform's endianness; you always get the bytes in the order you expect them.

谈场末日恋爱 2024-10-08 20:23:04

马克的答案当然是正确的答案。但自从他提到轮班运算符和不安全代码作为替代方案。我想分享一个不太常见的替代方案。使用具有显式布局的结构。这在原理上类似于 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);

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

Marc's answer is of course the right answer. But since he mentioned the shift operators and unsafe code as an alternative. I would like to share a less common alternative. Using a struct with Explicit layout. This is similar in principal to a C/C++ union.

Here is an example of a struct that can be used to get to the component bytes of the Int32 data type and the nice thing is that it is two way, you can manipulate the byte values and see the effect on the 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);
    }
  }

The above can now be used as follows

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

Of course the immutability police may not be excited about the last possiblity :)

各自安好 2024-10-08 20:23:04

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

This may be OT but if you are serializing a lot of primitive types or POD structures, Google Protocol Buffers for .Net might be useful to you. This addresses the endianness issue @Marc raised above, among other useful features.

十二 2024-10-08 20:23:04

如果您来自 Google

老问题的替代答案是指 John Skeet 的库,该库提供了一些工具,可让您将原始数据类型直接写入带有索引偏移量的 byte[] 中。如果您需要性能,则比 BitConverter 好得多。

旧线程在此讨论此问题

John Skeet 的库位于此处

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

If you came here from Google

Alternative answer to an older question refers to John Skeet's Library that has tools for letting you write primitive data types directly into a byte[] with an Index offset. Far better than BitConverter if you need performance.

Older thread discussing this issue here

John Skeet's Libraries are here

Just download the source and look at the MiscUtil.Conversion namespace. EndianBitConverter.cs handles everything for you.

想念有你 2024-10-08 20:23:04

使用 MemoryMarshalSpan

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

BenchmarkDotnet

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

Heap allocation free using MemoryMarshal and Span

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

BenchmarkDotnet

|            Method |      Mean |     Error |    StdDev | Allocated |
|------------------ |----------:|----------:|----------:|----------:|
| MemoryMarshalTest | 0.0023 ns | 0.0017 ns | 0.0014 ns |         - |
何以畏孤独 2024-10-08 20:23:04

这里的大多数答案要么是“不安全”,要么是 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

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

Most of the answers here are either 'UnSafe" or not LittleEndian safe. BitConverter is not LittleEndian safe.
So building on an example in here (see the post by PZahra) I made a LittleEndian safe version simply by reading the byte array in reverse when 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));
}

It returns this:

True
0xDCBAABCDFFFE1608

which is the exact hex that went into the byte array.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文