.NET(C#): 当BitConverter类型遇到数组
众所周知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