47

I have a memoryStream instance and it is closed.

I already have tried:

memoryStream.Flush();
memoryStream.Position=0;

To reopen the memory stream but it does not work. How can I reopen a closed memory stream?

halfer
  • 19,824
  • 17
  • 99
  • 186
olidev
  • 20,058
  • 51
  • 133
  • 197
  • 3
    Don't close it? Or use [MemoryStream.ToArray](http://msdn.microsoft.com/en-us/library/system.io.memorystream.toarray.aspx) and create a new stream. – dtb Mar 01 '12 at 00:25
  • Devn; If you've formally closed the stream then you can't re-open it - but perhaps it might help to explain what it is you're managing and why there's the need to close the stream in the first place. Ultimately, what are you trying to achieve with your streams ? – Russ Clarke Mar 01 '12 at 01:04
  • 6
    @RussClarke It's usually because some third party library "helpfully" closed your stream for you. It's not uncommon, unfortunately. – Roman Starkov Mar 14 '16 at 01:51

4 Answers4

46

You can clone the original one and then use the clone, even when the original has been closed. Even though the original one is created with a capacity of 1000, ToArray() returns a 2 element array. ToBuffer() on the other hand gets you the entire buffer, which is what you don't want.

MemoryStream original = new MemoryStream(1000);
original.WriteByte(4);
original.WriteByte(5);

MemoryStream dolly = new MemoryStream(original.ToArray());
dolly.Seek(0, SeekOrigin.Begin);
Greg Biles
  • 941
  • 2
  • 10
  • 10
  • 2
    Does clone copy the buffer? Or just point to the same backing byte[]? I'm trying to get .Length out of a closed MemoryStream (stupid APIs think it's good to write **and** close a stream...) –  Apr 28 '14 at 20:31
  • It copies the buffer. See ToArray() here: http://referencesource.microsoft.com/#mscorlib/system/io/memorystream.cs,1a4dcb744a23ba6f – Simon Giles Jun 17 '15 at 17:31
30

try this:

memoryStream = new MemoryStream(memoryStream.ToArray());
Tom
  • 964
  • 9
  • 25
Andrew Pope
  • 317
  • 3
  • 4
13

How can I reopen a closed memory stream?

You can't reopen the stream. If you need to "reset" the stream, just assign it a new instance:

memoryStream = new MemoryStream();
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 4
    but how can I reuse a closed memory stream? – olidev Mar 01 '12 at 00:26
  • 2
    As Reed said, you can't. Don't close it if you need it later. If you can't change the fact that it was closed, you will have to create a new one. – Eric J. Mar 01 '12 at 00:56
  • Indeed, but as you hinted in your question, you could perhaps use Flush and Position, in lieu of closing the stream ? – Russ Clarke Mar 01 '12 at 01:03
10

This is an old, old question, but I'm reacting to the fact that the accepted answer isn't really useful and the highest-voted answer says that using .ToArray() is better than .GetBuffer(). I think that in many, perhaps most, situations using .GetBuffer() is significantly better than using .ToArray().

Here's an example of the problem of a memory stream getting closed despite your desire to continue using it:

  /// <summary>
  /// Method that gets called by ManagedResource.WriteData() in project CodeAnalysis during code 
  /// emitting to get the data for an embedded resource file.
  /// </summary>
  /// <param name="resourceFullFilename">full path and filename for resource file to embed</param>
  /// <returns>MemoryStream containing .resource file data - caller will dispose it</returns>
  private static MemoryStream ProvideResourceData(string resourceFullFilename)
  {
     MemoryStream shortLivedBackingStream = new MemoryStream();
     using (ResourceWriter resourceWriter = new ResourceWriter(shortLivedBackingStream))
     {
        using (ResXResourceReader resourceReader = new ResXResourceReader(resourceFullFilename))
        {
           IDictionaryEnumerator dictionaryEnumerator = resourceReader.GetEnumerator();
           while (dictionaryEnumerator.MoveNext())
           {
              string resourceKey = dictionaryEnumerator.Key as string;
              if (resourceKey != null)  // Should not be possible
                 resourceWriter.AddResource(resourceKey, dictionaryEnumerator.Value);
           }
        }
     }

     return new MemoryStream(shortLivedBackingStream.GetBuffer());
  }

The ResourceWriter class needs a backing stream so I give it a newly-created memory stream. But when ResourceWriter is no longer needed it closes the backing stream. Then I create a new MemoryStream based on the backing stream's buffer, which works fine, even though it is closed.

In this situation I happen to know that the calling program is going to use the provided memory stream to copy the data to another buffer and then close the memory stream immediately. So there is no need to create a new byte array, and there is a performance advantage to not creating a new byte array.

Thanks to @JoshVarty for showing how to avoid the problem of MemoryStream getting closed here: https://github.com/dotnet/roslyn/issues/7791

RenniePet
  • 11,420
  • 7
  • 80
  • 106
  • "In this situation I happen to know that the calling program is going to..." - But that's a bit of a code smell, isn't it? Someone else who comes along to maintain this method might not have that knowledge. Ideally, the method should work independently and like a black box. Sometimes, that's much easier said than done :). – dcp Mar 11 '19 at 19:34