Reputation: 43
When I'm trying to convert an object into byte array I'm getting a wierd array. this is the code:
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
the result is this:
"00 01 00 00 00 FF FF FF FF 01 00 00 00 00 00 00 00 04 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 "
Can somebody explain to me WHY?:) the optimal result should be only "32 00 00 00".
Upvotes: 1
Views: 1772
Reputation: 630
Serialization process uses extra bytes to store information about types - it's the only way to ensure that serialized data will be deserialized into same objects of same types. If you absolutely sure in what you doing and want to avoid any extra bytes, you may use your own serialization and make your formatter and serializers, which is very complicated. Or, you could use marshalling:
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);
And to convert bytes to object:
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);
This is quite slow and unsafe to use in most cases, but it's easiest way to strictly convert object to byte[] without implementing serialization and without [Serializable] attribute.
Upvotes: 0
Reputation: 39055
The serialized byte array has both the data itself and the type info. That's why you get more info than you expect. That's neccessary for later deserializing.
Upvotes: 1
Reputation: 7666
The extra stuff in the results would be the BinaryFormatter object. You're not just outputting int obj = 50, you're outputting everything included in the BinaryFormatter as well.
Upvotes: 0
Reputation: 64118
You're conflating BinaryFormatter
serialization with an object's in memory format. What is written to the stream is merely an implementation detail of the BinaryFormatter
and should not be relied upon for any interprocess communication not using BinaryFormatter
.
If you're looking for the byte representation of the built-in types, use BitConverter.GetBytes
(for strings use the appropriate Encoding.GetBytes
).
Upvotes: 2
Reputation: 726919
Since serializer needs to provide enough information to deserialize the data back, it must include some metadata about the object being serialized. Specifically, the
53 79 73 74 65 6D 2E 49 6E 74 33 32
part stands for System.Int32
If you use BinaryWriter
and its Write(Int32)
method instead, you'll get the desired effect: your memory stream will contain just the four bytes from your integer. You wouldn't be able to deserialize it without knowing that you wrote an Int32
into the stream.
Upvotes: 8