对于原始数组的序列化,我想知道如何将Primitive[]转换为其相应的byte[](例如,将int [128]转换为byte [512],或将ushort []转换为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倍。
但是,如果数组长度(对于Int32)超过200/300个值,则此解决方案会变慢。
强制类型转换?
C#似乎不能直接将Int[]转换为byte[]或bool[]转换为byte[]。
BitConverter.GetBytes()
此解决方案有效,但它在循环遍历我的int[]时每次都分配一个新的byte[]。性能当然很差。
Marshal.Copy
是的,这个解决方案也有效,但与前面的BitConverter相同,存在相同的问题。
C++ hack
由于C#不允许直接转换,所以在查看存储在数组数据之前4个字节的长度后,我尝试了一些C++ hack。
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);
我成功将我的int [128]获取到C ++中,切换数组长度并将正确的地址分配给我的“output”变量,但C#只返回一个byte [1]。看来我不能这么容易地修改托管变量。
因此,我真的开始认为所有我想要实现的这些类型转换在C#中都是不可能的(int []-> byte [],bool []-> byte [],double []-> byte [] ...)而不需要分配/复制...
我漏掉了什么?
byte[]
来保存原始数据(不需要序列化,但检索数据比较棘手)。 - Sinatr