C# Object Binary Serialization
Asked Answered
S

6

36

I want to make a binary serialize of an object and the result to save it in a database.

Person person = new Person();
person.Name = "something";

MemoryStream memorystream = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(memorystream, person);

How can I transform memorystream in a string type to be saved in database, and after this to be able to deserialize the object?

Slipsheet answered 17/11, 2009 at 13:52 Comment(0)
H
61

What you're really asking for is a safe way of representing arbitrary binary data as text and then converting it back again. The fact that it stores a serialized object is irrelevant.

The answer is almost to use Base 64 (e.g. Convert.ToBase64String and Convert.FromBase64String). Do not use Encoding.UTF8.GetString or anything similar - your binary data is not encoded text data, and shouldn't be treated as such.

However, does your database not have a data type for binary data? Check for BLOB, IMAGE and BINARY types...

Hagiarchy answered 17/11, 2009 at 13:57 Comment(5)
bytes to string --- needs some Encoding.Galligaskins
@loneshark99: I don't understand your comment at all. If this is arbitrary binary data - rather than encoded text - then using an Encoding would be precisely the wrong approach.Hagiarchy
I am learning , but I am wondering why Encoding is not the right approach and ToBase64String is.Galligaskins
@loneshark99: Because an Encoding is designed for data that is inherently textual - it converts that text to binary data, whereas base64 and hex are designed for representing inherently binary arbitrary data as text without losing information.Hagiarchy
Thanks that makes sense!. I always get confused about encoding. Thank you!!Galligaskins
F
45

Here's the sample. TData must be marked [Serializable] and all fields type also.

    private static TData DeserializeFromString<TData>(string settings)
    {
        byte[] b = Convert.FromBase64String(settings);
        using (var stream = new MemoryStream(b))
        {
            var formatter = new BinaryFormatter();
            stream.Seek(0, SeekOrigin.Begin);
            return (TData)formatter.Deserialize(stream);
        }
    }

    private static string SerializeToString<TData>(TData settings)
    {
        using (var stream = new MemoryStream())
        {
            var formatter = new BinaryFormatter();
            formatter.Serialize(stream, settings);
            stream.Flush();
            stream.Position = 0;
            return Convert.ToBase64String(stream.ToArray());
        }
    }
Fanion answered 30/5, 2011 at 18:16 Comment(0)
G
19
//-------write to database-------------------------
Person person = new Person();
person.name = "Firstnm  Lastnm";
MemoryStream memorystream = new MemoryStream(); 
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(memorystream, person);
byte[] yourBytesToDb = memorystream.ToArray();
//here you write yourBytesToDb to database


//----------read from database---------------------
//here you read from database binary data into yourBytesFromDb
MemoryStream memorystreamd = new MemoryStream(yourBytesFromDb);
BinaryFormatter bfd = new BinaryFormatter();
Person deserializedperson = bfd.Deserialize(memorystreamd) as Person;
Glover answered 4/1, 2012 at 17:55 Comment(2)
There should be a using around the MemoryStreamMaramarabel
There is a Warning for .Net5.0 and a few other flavors: "The BinaryFormatter type is dangerous and is not recommended for data processing. Applications should stop using BinaryFormatter as soon as possible, even if they believe the data they're processing to be trustworthy. BinaryFormatter is insecure and can't be made secure." learn.microsoft.com/en-us/dotnet/standard/serialization/…Disjunction
B
14

I used something like this

MemoryStream memoryStream = new MemoryStream();
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(memoryStream, Person);
memoryStream.Flush();
memoryStream.Position = 0;
string value = Convert.ToBase64String(memoryStream.ToArray());
Basil answered 17/11, 2009 at 13:57 Comment(1)
You don't need to rewind a MemoryStream before calling ToArray - it returns the whole stream's data regardless of the current position. Likewise Flush doesn't do anything on a MemoryStream, although it's a good idea for streams in general.Hagiarchy
D
3

Basically, don't save the data as string to the database, there are blob fields available to store binary data.

If you really need to have the data as string, you'll need to convert your byte[] to a string using base64 encoding, and to grab the byte[] from a string use decoding.

Dissociate answered 17/11, 2009 at 13:57 Comment(0)
J
0

Have you not looked into converting the memorystream into a base64hex string to be put into the database?

 byte[] mStream = memorystream.ToArray();
 string sConvertdHex = System.Convert.ToBase64String(mStream)

Then you can dump the contents sConvertdHex to the database. To deserialize it you need to do the reverse

 byte[] mData = System.Convert.FromBase64String(...)

then deserialize mData back to your object.

Juster answered 17/11, 2009 at 13:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.