众所周知BitConverter类型可以从基元类型中获取其在内存中的原始字节数据。但是它的方法只支持单个对象,而不支持相应的数组重载。为了可以快速从基元类型数组中获取字节,可以借助另一个类型:System.Buffer类型。他可以快速获取甚至是设置基元数据类型数组中的字节。
因此,BitConverter类型能做到的,Buffer类型也能做到,比如下面的BitConverter代码:
var d = 123.456;
var bytes = BitConverter.GetBytes(d);
Console.WriteLine(BitConverter.ToString(bytes));
使用Buffer类型也可以做到。步骤是需要先通过Buffer.ByteLength方法来获取字节数组长度,然后使用Buffer.BlockCopy方法来把原始字节复制到指定的字节数组中就可以了。
代码:
//声明数组
var array = new double[] { 123.456 };
//通过Buffer.ByteLength获取字节数组长度
var bytes = new byte[Buffer.ByteLength(array)];
//通过Buffer.BlockCopy复制字节数据
Buffer.BlockCopy(array, 0, bytes, 0, bytes.Length);
Console.WriteLine(BitConverter.ToString(bytes));
上面两段代码都会输出:
77-BE-9F-1A-2F-DD-5E-40
那么使用这种方法就可以快速获取数组的原始字节,就像这样:
//声明数组
var array = new int[] { 1, 2, 3 };
//通过Buffer.ByteLength获取字节数组长度
var bytes = new byte[Buffer.ByteLength(array)];
//通过Buffer.BlockCopy复制字节数据
Buffer.BlockCopy(array, 0, bytes, 0, bytes.Length);
Console.WriteLine(BitConverter.ToString(bytes));
输出:
01-00-00-00-02-00-00-00-03-00-00-00
最后写了两个方法可以实现基元数据类型数组和字节数组的互转。不过,实现上有一点不爽的是Buffer.ByteLength方法只能从基元数据类型数组中获取字节数组的长度。但是没有提供相反的方法,为了从字节数组中获取资源数据类型数组的长度,无奈将字节数组的长度除以泛型T类型所占空间大小,这个大小是通过System.Runtime.InteropServices.Marshal.SizeOf方法来获取的。
代码:
//将基元数据类型数组转换成字节数组
static byte[] ToBytes<T>(T[] array) where T : struct
{
if (array == null)
{
throw new ArgumentNullException("array");
}
var bytes = new byte[Buffer.ByteLength(array)];
Buffer.BlockCopy(array, 0, bytes, 0, bytes.Length);
return bytes;
}
//将字节数组转换成基元数据类型数组
static T[] FromBytes<T>(byte[] bytes) where T : struct
{
if (bytes == null)
{
throw new ArgumentNullException("bytes");
}
var array = new T[bytes.Length / System.Runtime.InteropServices.Marshal.SizeOf(typeof(T))];
Buffer.BlockCopy(bytes, 0, array, 0, bytes.Length);
return array;
}
可以这样用:
var array = new int[] { 1, 2, 3 };
var bytes = ToBytes(array);
//int[] to byte[]
Console.WriteLine(BitConverter.ToString(bytes));
//byte[] to int[]
array = FromBytes<int>(bytes);
foreach(var i in array)
Console.WriteLine(i);
输出:
01-00-00-00-02-00-00-00-03-00-00-00
1
2
3