35

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?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Emanuel
  • 6,622
  • 20
  • 58
  • 78

6 Answers6

59

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...

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • bytes to string --- needs some Encoding. – loneshark99 May 04 '17 at 06:26
  • 2
    @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. – Jon Skeet May 04 '17 at 06:33
  • 1
    I am learning , but I am wondering why Encoding is not the right approach and ToBase64String is. – loneshark99 May 04 '17 at 06:37
  • 5
    @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. – Jon Skeet May 04 '17 at 06:44
  • Thanks that makes sense!. I always get confused about encoding. Thank you!! – loneshark99 May 04 '17 at 06:49
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());
        }
    }
Siarhei Kuchuk
  • 5,296
  • 1
  • 28
  • 31
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;
Vinod Srivastav
  • 3,644
  • 1
  • 27
  • 40
Ramakrishna Talla
  • 1,011
  • 12
  • 7
  • 2
    There should be a `using` around the `MemoryStream` – j00hi Aug 01 '16 at 19:49
  • 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." https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide – Stefan Wuebbe Feb 11 '22 at 22:20
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());
Dan Atkinson
  • 11,391
  • 14
  • 81
  • 114
Adriaan Stander
  • 162,879
  • 31
  • 289
  • 284
  • 11
    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. – Jon Skeet Nov 17 '09 at 13:59
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.

Jan Jongboom
  • 26,598
  • 9
  • 83
  • 120
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.

Mike Chaliy
  • 25,801
  • 18
  • 67
  • 105
t0mm13b
  • 34,087
  • 8
  • 78
  • 110