当我试图将一个对象转换为字节数组时,我得到了一个奇怪的数组。 这是代码:
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, obj);
Console.WriteLine(ByteArrayToString(ms.ToArray()));
}
//int obj = 50;
//string ByteArrayToString(byte[] byteArr) the functionality of this method is pretty obvious
结果如下:
“00 01 00 00 00 FF FF FF 01 00 00 00 00 00 00 00 01 01 00 00 00 0C 53 79 73 74 65 6D 2E 49 6E 74 33 32 01 00 00 00 07 6D 5F 76 61 6C 75 65 00 08 32 00 00 00 0B“
有人可以向我解释为什么?:)最佳结果应该只是“32 00 00 00”。
答案 0 :(得分:8)
由于序列化程序需要提供足够的信息来反序列化数据,因此它必须包含有关要序列化的对象的一些元数据。具体来说,
53 79 73 74 65 6D 2E 49 6E 74 33 32
部分代表System.Int32
如果您使用BinaryWriter
及其Write(Int32)
方法,您将获得所需的效果:您的内存流将只包含整数中的四个字节。如果不知道你在流中写了Int32
,就无法反序列化。
答案 1 :(得分:2)
您将BinaryFormatter
序列化与对象的以内存格式混合。写入流的内容仅仅是BinaryFormatter
的实现细节,不应依赖于不使用BinaryFormatter
的任何进程间通信。
如果您正在寻找内置类型的字节表示,请使用BitConverter.GetBytes
(对于字符串,请使用相应的Encoding.GetBytes
)。
答案 2 :(得分:1)
序列化字节数组包含数据本身和类型信息。这就是为什么你获得的信息超出预期。这对于后来的反序列化是必要的。
答案 3 :(得分:0)
结果中的额外内容将是BinaryFormatter对象。你不只是输出int obj = 50,你也输出了BinaryFormatter中包含的所有内容。
答案 4 :(得分:0)
序列化过程使用额外的字节来存储有关类型的信息 - 这是确保将序列化数据反序列化为相同类型的相同对象的唯一方法。 如果您完全确定自己在做什么并且想要避免任何额外的字节,那么您可以使用自己的序列化并制作格式化程序和序列化程序,这非常复杂。或者,您可以使用编组:
var size = Marshal.SizeOf(your_object);
// Both managed and unmanaged buffers required.
var bytes = new byte[size];
var ptr = Marshal.AllocHGlobal(size);
// Copy object byte-to-byte to unmanaged memory.
Marshal.StructureToPtr(font.LogFont, ptr, false);
// Copy data from unmanaged memory to managed buffer.
Marshal.Copy(ptr, bytes, 0, size);
// Release unmanaged memory.
Marshal.FreeHGlobal(ptr);
并将字节转换为对象:
var bytes = new byte[size];
var ptr = Marshal.AllocHGlobal(size);
Marshal.Copy(bytes, 0, ptr, size);
var your_object = (YourType)Marshal.PtrToStructure(ptr, typeof(YourType));
Marshal.FreeHGlobal(ptr);
在大多数情况下使用这种方法非常慢且不安全,但这是将对象严格转换为byte []而不实现序列化且没有[Serializable]属性的最简单方法。