对于原语数组的序列化,我想知道如何将Primitive[]转换为相应的byte[]。( int128 to a byte512,ushort[] to a byte[].)目标可以是一个内存流,一个网络消息,一个文件,任何东西。其目标是性能(序列化和反序列化时间),能够一次编写一个byte[]流,而不是循环所有值,或者使用某种转换器进行分配。
一些已经探讨过的解决办法:
规则循环以写入/读取
//array = any int[];
myStreamWriter.WriteInt32(array.Length);
for(int i = 0; i < array.Length; ++i)
myStreamWriter.WriteInt32(array[i]);此解决方案适用于序列化和反序列化,比使用标准System.Runtime.Serialization和BinaryFormater序列化/反序列化单个int或其中几个int快100倍。
但是,如果array.Length包含超过200/300个值(对于Int32),则此解决方案会变慢。
Cast?
似乎C#不能直接将Int[]转换为byte[],也不能将bool[]转换为byte[]。
BitConverter.Getbytes()
这个解决方案可以工作,但是它通过我的byte[]在循环的每个调用中分配一个新的int[]。当然,表演是可怕的
Marshal.Copy
是的,这个解决方案也能工作,但与以前的BitConverter解决方案相同。
C++ hack
由于C#中不允许直接强制转换,所以在内存中看到数组长度在数组数据开始之前存储了4个字节后,我尝试了一些C++哈克。
ARRAYCAST_API void Cast(int* input, unsigned char** output)
{
// get the address of the input (this is a pointer to the data)
int* count = input;
// the size of the buffer is located just before the data (4 bytes before as this is an int)
count--;
// multiply the number of elements by 4 as an int is 4 bytes
*count = *count * 4;
// set the address of the byte array
*output = (unsigned char*)(input);
}而C#则呼吁:
byte[] arrayB = null;
int[] arrayI = new int[128];
for (int i = 0; i < 128; ++i)
arrayI[i] = i;
// delegate call
fptr(arrayI, out arrayB);我成功地将我的int128检索到C++中,切换数组长度,并影响到我的'output‘var的右入口,但是C#只是作为返回检索byte1。看来我不可能那么容易地黑掉这样的托管变量。
因此,我开始认为,我想要实现的所有这些类型在C# (int[] -> byte[],bool[] -> byte[],double[] -> byte[].)中是不可能的。没有分配/复制..。
我错过了什么?
发布于 2015-06-22 15:15:07
使用Buffer.BlockCopy怎么样?
// serialize
var intArray = new[] { 1, 2, 3, 4, 5, 6, 7, 8 };
var byteArray = new byte[intArray.Length * 4];
Buffer.BlockCopy(intArray, 0, byteArray, 0, byteArray.Length);
// deserialize and test
var intArray2 = new int[byteArray.Length / 4];
Buffer.BlockCopy(byteArray, 0, intArray2, 0, byteArray.Length);
Console.WriteLine(intArray.SequenceEqual(intArray2)); // true请注意,BlockCopy仍然在幕后分配/复制。我相当肯定,这在托管代码中是不可避免的,而且BlockCopy可能在这方面得到了很好的效果。
https://stackoverflow.com/questions/30983019
复制相似问题