TalBin
TalBin

Reputation: 43

Object-to-bytes conversion

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

Answers (5)

Aberro
Aberro

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

JotaBe
JotaBe

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

tmesser
tmesser

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

user7116
user7116

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

Sergey Kalinichenko
Sergey Kalinichenko

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

Related Questions