Converting Stream to String and back…what are we missing? [c#]


I have just tested this and works fine.

string test = "Testing 1-2-3";

// convert string to stream
byte[] byteArray = Encoding.ASCII.GetBytes(test);
MemoryStream stream = new MemoryStream(byteArray);

// convert stream to string
StreamReader reader = new StreamReader(stream);
string text = reader.ReadToEnd();

If stream has already been written to, you might want to seek to the beginning before first before reading out the text: stream.Seek(0, SeekOrigin.Begin);


I want to serialize objects to strings, and back.

We use protobuf-net to turn an object into a Stream and back, successfully.

However, Stream to string and back... not so successful. After going through StreamToString and StringToStream, the new Streamisn't deserialized by protobuf-net; it raises an Arithmetic Operation resulted in an Overflow exception. If we deserialize the original stream, it works.

Our methods:

public static string StreamToString(Stream stream)
    stream.Position = 0;
    using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
        return reader.ReadToEnd();

public static Stream StringToStream(string src)
    byte[] byteArray = Encoding.UTF8.GetBytes(src);
    return new MemoryStream(byteArray);

Our example code using these two:

MemoryStream stream = new MemoryStream();
Serializer.Serialize<SuperExample>(stream, test);
stream.Position = 0;
string strout = StreamToString(stream);
MemoryStream result = (MemoryStream)StringToStream(strout);
var other = Serializer.Deserialize<SuperExample>(result);

a UTF8 MemoryStream to String conversion:

var res = Encoding.UTF8.GetString(stream.GetBuffer(),0 , stream.GetBuffer().Length)

Could we save delegates in a file (C#)

This is a pretty risky thing to do.

While it's true that you can serialize and deserialize a delegate just like any other object, the delegate is a pointer to a method inside the program that serialized it. If you deserialize the object in another program, you'll get a SerializationException - if you're lucky.

For instance, let's modify darin's program a bit:

class Program
   public class Foo
       public Func<string> Del;

   static void Main(string[] args)
       Func<string> a = (() => "a");
       Func<string> b = (() => "b");

       Foo foo = new Foo();
       foo.Del = a;


       Foo bar = ReadFoo();


   public static void WriteFoo(Foo foo)
       BinaryFormatter formatter = new BinaryFormatter();
       using (var stream = new FileStream("test.bin", FileMode.Create, FileAccess.Write, FileShare.None))
           formatter.Serialize(stream, foo);

   public static Foo ReadFoo()
       Foo foo;
       BinaryFormatter formatter = new BinaryFormatter();
       using (var stream = new FileStream("test.bin", FileMode.Open, FileAccess.Read, FileShare.Read))
           foo = (Foo)formatter.Deserialize(stream);

       return foo;

Run it, and you'll see that it creates the object, serializes it, deserializes it into a new object, and when you call Del on the new object it returns "a". Excellent. Okay, now comment out the call to WriteFoo, so that the program it's just deserializing the object. Run the program again and you get the same result.

Now swap the declaration of a and b and run the program. Yikes. Now the deserialized object is returning "b".

This is happening because what's actually being serialized is the name that the compiler is assigning to the lambda expression. And the compiler assigns names to lambda expressions in the order it finds them.

And that's what's risky about this: you're not serializing the delegate, you're serializing a symbol. It's the value of the symbol, and not what the symbol represents, that gets serialized. The behavior of the deserialized object depends on what the value of that symbol represents in the program that's deserializing it.

To a certain extent, this is true with all serialization. Deserialize an object into a program that implements the object's class differently than the serializing program did, and the fun begins. But serializing delegates couples the serialized object to the symbol table of the program that serialized it, not to the implementation of the object's class.

If it were me, I'd consider making this coupling explicit. I'd create a static property of Foo that was a Dictionary<string, Func<string>>, populate this with keys and functions, and store the key in each instance rather than the function. This makes the deserializing program responsible for populating the dictionary before it starts deserializing Foo objects. To an extent, this is exactly the same thing that using the BinaryFormatter to serialize a delegate is doing; the difference is that this approach makes the deserializing program's responsibility for assigning functions to the symbols a lot more apparent.

A delegate is a method pointer, I might misunderstand when you say save, but the location added to the delegate at runtime might not exist any longer if you try and save and restore the address.