我以为.net有某种简单的转换方法可以用来将int转换成字节数组呢?我做了一个快速搜索,所有的解决方案都是位屏蔽/一次移位一个字节,就像“美好的旧日子”。难道某个地方没有ToByteArray()方法吗?
mi7gmzs61#
2020年的更新-BinaryPrimitives现在应该比BitConverter更受欢迎。它提供了特定于endian的API,并且分配性更低。
BinaryPrimitives
BitConverter
byte[] bytes = BitConverter.GetBytes(i);
不过也要注意,您 * 可能 * 希望检查BitConverter.IsLittleEndian,以查看它将以哪种方式出现!注意,如果你重复地这样做,你可能想通过移位操作(>>/<<)或者使用unsafe代码来避免所有那些短暂的数组分配。移位操作还有一个优点,那就是它们不受平台字节序的影响;你 * 总是 * 按照你期望的顺序得到字节。
BitConverter.IsLittleEndian
>>
<<
unsafe
goqiplq22#
Marc的答案当然是正确的。但是既然他提到了移位操作符和不安全代码作为替代方案。我想分享一个不太常见的替代方案。使用Explicit布局的结构体。这在原理上类似于C/C++ union。这是一个可以用来获取Int 32数据类型的组成字节的结构体的例子,它的好处是它是双向的,你可以操作字节值,并查看对Int 32数据类型的影响。
Explicit
union
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);
当然,不变性警察可能不会对最后一种可能性感到兴奋:)
avkwfej43#
这可能是OT,但是如果你要序列化大量的原语类型或POD结构,Google Protocol Buffers for .Net可能会对你有用,它解决了上面@Marc提出的字节序问题,以及其他有用的特性。
u59ebvdq4#
"如果你是从谷歌来的"对于一个老问题的另一个答案是John Skeet的Library,它提供了一些工具,可以让你直接将原始数据类型写入一个带有索引偏移量的byte[]中,如果你需要性能的话,它比BitConverter好得多。Older thread discussing this issue hereJohn Skeet's Libraries are here只需下载源代码并查看MiscUtil.Conversion名称空间。EndianBitConverter.cs会为您处理一切。
MiscUtil.Conversion
EndianBitConverter.cs
ijnw1ujt5#
使用MemoryMarshal和Span释放堆分配
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 | - |
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
这就是进入字节数组的十六进制数。
6条答案
按热度按时间mi7gmzs61#
2020年的更新-
BinaryPrimitives
现在应该比BitConverter
更受欢迎。它提供了特定于endian的API,并且分配性更低。不过也要注意,您 * 可能 * 希望检查
BitConverter.IsLittleEndian
,以查看它将以哪种方式出现!注意,如果你重复地这样做,你可能想通过移位操作(
>>
/<<
)或者使用unsafe
代码来避免所有那些短暂的数组分配。移位操作还有一个优点,那就是它们不受平台字节序的影响;你 * 总是 * 按照你期望的顺序得到字节。goqiplq22#
Marc的答案当然是正确的。但是既然他提到了移位操作符和不安全代码作为替代方案。我想分享一个不太常见的替代方案。使用
Explicit
布局的结构体。这在原理上类似于C/C++union
。这是一个可以用来获取Int 32数据类型的组成字节的结构体的例子,它的好处是它是双向的,你可以操作字节值,并查看对Int 32数据类型的影响。
现在可以按如下方式使用上述内容
当然,不变性警察可能不会对最后一种可能性感到兴奋:)
avkwfej43#
这可能是OT,但是如果你要序列化大量的原语类型或POD结构,Google Protocol Buffers for .Net可能会对你有用,它解决了上面@Marc提出的字节序问题,以及其他有用的特性。
u59ebvdq4#
"如果你是从谷歌来的"
对于一个老问题的另一个答案是John Skeet的Library,它提供了一些工具,可以让你直接将原始数据类型写入一个带有索引偏移量的byte[]中,如果你需要性能的话,它比
BitConverter
好得多。Older thread discussing this issue here
John Skeet's Libraries are here
只需下载源代码并查看
MiscUtil.Conversion
名称空间。EndianBitConverter.cs
会为您处理一切。ijnw1ujt5#
使用MemoryMarshal和Span释放堆分配
基准点网
ktecyv1j6#
这里的大多数答案不是“不安全”就是不是LittleEndian安全。BitConverter不是LittleEndian安全的。因此,基于here中的一个示例(参见PZahra的帖子),我创建了一个LittleEndian安全版本,方法是在BitConverter.IsLittleEndian == true时反向阅读字节数组
它返回以下内容:
这就是进入字节数组的十六进制数。