如何将 Primitive[] 转换为 byte[]
How to Convert Primitive[] to byte[]
对于Primitive Array的序列化,我想知道如何将Primitive[]转换成他对应的byte[]。 (即 int[128] 到 byte[512],或 ushort[] 到 byte[]...)
目标可以是内存流、网络消息、文件或任何东西。
目标是性能(序列化和反序列化时间),以便能够用一些流一次性写入一个字节 [] 而不是循环“遍历”所有值,或者使用一些转换器进行分配。
一些已经探索的解决方案:
常规循环到 write/read
//array = any int[];
myStreamWriter.WriteInt32(array.Length);
for(int i = 0; i < array.Length; ++i)
myStreamWriter.WriteInt32(array[i]);
此解决方案适用于序列化和反序列化,并且比使用标准 System.Runtime.Serialization 结合 BinaryFormater 到 Serialize/Deserialize 单个 int 或其中几个快 100 倍。
但如果 array.Length 包含超过 200/300 个值(对于 Int32),此解决方案会变慢。
投?
似乎 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' var 的正确地址,但 C# 仅检索一个字节 [1] 作为 return.看来我不能那么轻易地破解一个托管变量。
所以我真的开始认为我想要实现的所有这些转换在 C# 中是不可能的 (int[] -> byte[], bool[] -> byte[], double[] -> byte[ ]...) 没有 Allocating/copying...
我错过了什么?
使用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
仍在幕后 allocating/copying。我相当确定这在托管代码中是不可避免的,并且 BlockCopy
可能已经达到了它的最佳状态。
对于Primitive Array的序列化,我想知道如何将Primitive[]转换成他对应的byte[]。 (即 int[128] 到 byte[512],或 ushort[] 到 byte[]...) 目标可以是内存流、网络消息、文件或任何东西。 目标是性能(序列化和反序列化时间),以便能够用一些流一次性写入一个字节 [] 而不是循环“遍历”所有值,或者使用一些转换器进行分配。
一些已经探索的解决方案:
常规循环到 write/read
//array = any int[];
myStreamWriter.WriteInt32(array.Length);
for(int i = 0; i < array.Length; ++i)
myStreamWriter.WriteInt32(array[i]);
此解决方案适用于序列化和反序列化,并且比使用标准 System.Runtime.Serialization 结合 BinaryFormater 到 Serialize/Deserialize 单个 int 或其中几个快 100 倍。
但如果 array.Length 包含超过 200/300 个值(对于 Int32),此解决方案会变慢。
投?
似乎 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' var 的正确地址,但 C# 仅检索一个字节 [1] 作为 return.看来我不能那么轻易地破解一个托管变量。
所以我真的开始认为我想要实现的所有这些转换在 C# 中是不可能的 (int[] -> byte[], bool[] -> byte[], double[] -> byte[ ]...) 没有 Allocating/copying...
我错过了什么?
使用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
仍在幕后 allocating/copying。我相当确定这在托管代码中是不可避免的,并且 BlockCopy
可能已经达到了它的最佳状态。