简体   繁体   中英

Serializing to stream and then reading from stream

When trying to read from a MemoryStream (which was written to by an XmlWriter), it throws an ObjectDisposedException ("Cannot access a closed Stream.") .

I stumbled upon the fact that closing the XmlWriter in the middle of the 'using' statement allows to code to return without throwing. Something is fishy here.

    public static string SerializeToString(T obj)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(T));

        using (var stream = new MemoryStream())
        using (var writer = XmlWriter.Create(stream))
        {
            serializer.Serialize(writer, obj);

            writer.Flush();
            // Swapping the flush for close fixes the ObjectDisposedException 
            //writer.Close();
            stream.Position = 0;


            using (var reader = new StreamReader(stream))
            {
                return reader.ReadToEnd();
            }
        }
    }

This happens for both Silverlight and .NET 4.5.

After reading around I could read a string from the memory stream directly as per Jon's answer here return Encoding.UTF8.GetString(stream.GetBuffer(), 0, stream.Length);

But first I'd like to understand what is happening to cause the exception in the example code.

Closing the writer will also Close() the underlying stream object.

You don't need to close the writer explicitly, as the using statement will do that for you automatically at the end of the block.

using (var stream = new MemoryStream())
using (var writer = XmlWriter.Create(stream))
{       
    ...
    //writer.Close(); <=== don't do this
    ...
} // <=== stream and writer get closed here

The issue that the example code is exhibiting is double disposing (the StreamReader and the XmlWriter both dispose their BaseStream[MemoryStream]).

Putting the StreamReader into the top block of usings fixes the issue.

But in the end I didn't need to StreamReader to get the text out and went with the following:

        public static string SerializeToString(T obj)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(T));

            using (var memoryStream = new MemoryStream())
            using (var writer = XmlWriter.Create(memoryStream))
            {
                serializer.Serialize(writer, obj);
                return Encoding.UTF8.GetString(memoryStream.GetBuffer(), 0, (int)memoryStream.Length);
            }
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM