2

I have problem with serialization. I want to convert an object into a string and vice versa. I have two utility methods:

public
static byte[] Serialize(Object o)
{
   MemoryStream ms = new MemoryStream();
   BinaryFormatter bf1 = new BinaryFormatter();
   bf1.Serialize(ms, o);
   byte[] buffer = ms.ToArray();
   //string retStr = Convert.ToBase64String(buffer);
   return buffer;
}

public static object Deserialize(byte[] TheByteArray)
{
   //byte[] TheByteArray = Convert.FromBase64String(ParamStr);
   MemoryStream ms = new MemoryStream(TheByteArray);
   BinaryFormatter bf1 = new BinaryFormatter();
   ms.Position = 0;
   return bf1.Deserialize(ms);
}

My test code is:

Student obj = new Student ();
obj.UserName = "Admin";
obj.Password = "Password";
obj.lessonIds = new int[] { 1, 2, 3, 4, 5 };
obj.lessonNames= new string[] { "Spanish", "Maths" };
obj.Id= 43;
byte[] retByteArray = Crypto.Serialize(obj);

Student objNew = new Student ();
objNew = (Student )Crypto.Deserialize(retByteArray);

this code does not work. The error message is : Exception has been thrown by the target of an invocation. End of Stream encountered before parsing was completed.

End my main aim is convert object into string but I even cannot convert it into byte array

2
  • This isn't the bug, but you don't need to Student objNew = new Student (); before calling Deserialize. You are just creating an object and then replacing it with another one. Commented Jun 19, 2009 at 12:32
  • Re your comment - then simply, you are deserializing it incorrectly. It really isn't worth trying to write your own serialization code - I strongly recommend trying protobuf-net (caveat: I'm the author, but it is free). It took seconds to apply to your example, giving very efficient results without the risk of these annoying stream bugs. Commented Jun 19, 2009 at 18:28

3 Answers 3

1

I have just tried the original code and it work's fine however, you need to make sure that the student class definition is marked as [Serializable]

[Serializable]
public class Student
{
    public string UserName;
    public string Password;
    public int[] lessonIds;
    public string[] lessonNames;
    public int Id;
    public Student() { }
}
Sign up to request clarification or add additional context in comments.

Comments

0

That code works perfectly for me (I simply added the missing Student class. Is that code actually representative of your real code. In particular, buffer handling (maybe file IO) would be my first suspicion. But the bug isn't in the code you posted... it works fine.

As an aside... BinaryFormatter can be brittle, especially around different versions - you may want to consider alternative serializers. Ask for more info if you are interested.

Here it is runnable:

using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System;
static class Crypto
{
    static byte[] Serialize(object o)
    {
        MemoryStream ms = new MemoryStream();
        BinaryFormatter bf1 = new BinaryFormatter();
        bf1.Serialize(ms, o);
        byte[] buffer = ms.ToArray();
        //string retStr = Convert.ToBase64String(buffer);
        return buffer;
    }

    public static object Deserialize(byte[] TheByteArray)
    {
        //byte[] TheByteArray = Convert.FromBase64String(ParamStr);
        MemoryStream ms = new MemoryStream(TheByteArray);
        BinaryFormatter bf1 = new BinaryFormatter();
        ms.Position = 0;
        return bf1.Deserialize(ms);
    }
    [Serializable]
    class Student
    {
        public string UserName { get; set; }
        public string Password { get; set; }
        public int[] LessonIds { get; set; }
        public string[] LessonNames { get; set; }
        public int Id { get; set; }
    }
    static void Main()
    {
        Student obj = new Student();
        obj.UserName = "Admin";
        obj.Password = "Password";
        obj.LessonIds = new int[] { 1, 2, 3, 4, 5 };
        obj.LessonNames = new string[] { "Spanish", "Maths" };
        obj.Id = 43;
        byte[] retByteArray = Crypto.Serialize(obj);

        Student objNew = (Student)Crypto.Deserialize(retByteArray);
    }
}

2 Comments

For info, I jut ran it through protobuf-net for comparison: BinaryFormatter=363 bytes; protobuf-net=45 bytes...
Thank you everybody. I found my mistake. My student class implements ISerializable interface; when I remove it, it works. But I did not understand problem with interface.
0

You might be suffering from a race condition, because you're not closing the memory stream or your formatter when you're done serializing.

Try this:

public
static byte[] Serialize(Object o)
{
   using (MemoryStream ms = new MemoryStream())
   {
       BinaryFormatter bf1 = new BinaryFormatter();
       bf1.Serialize(ms, o);
       byte[] buffer = ms.ToArray();
       //string retStr = Convert.ToBase64String(buffer);
   }
   return buffer;
}

public static object Deserialize(byte[] TheByteArray)
{
   //byte[] TheByteArray = Convert.FromBase64String(ParamStr);
   using (MemoryStream ms = new MemoryStream(TheByteArray))
   {
       BinaryFormatter bf1 = new BinaryFormatter();
       ms.Position = 0;
       var result = bf1.Deserialize(ms);
   }
   return result;
}

6 Comments

@Marc You don't think so? Why?
You aren't doing anything extra in the code before getting the ToArray(), so you aren't changing the results. All you add is a Dispose() to something that has an empty Dispose() implementation. Don't get me wrong, I always dispose these things too - but that isn't the bug.
There isn't a race condition there. It is a good and worthwhile thought, but it doesn't stand much scrutiny.
@Marc Ok I see, but then why do both MemoryStream and BinaryFormatter have a Close? What's the point if they're not releasing resources? Should it rather be a (try/finally/Close)instead of the using?
BinaryFormatter doesn't have a Close(). MemoryStream has one because every Stream has one. I fully agree that it would be better practice to use "using" here... simply that this isn't causing the bug.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.