Can you keep a StreamReader from disposing the underlying stream?

C#File Io

C# Problem Overview


Is there a way to do this:

this.logFile = File.Open("what_r_u_doing.log", FileMode.OpenOrCreate, FileAccess.ReadWrite);

using(var sr = new StreamReader(this.logFile))
{
    // Read the data in
}

// ... later on in the class ...

this.logFile = File.Open("what_r_u_doing.log", FileMode.OpenOrCreate, FileAccess.ReadWrite);

using(var sw = new StreamWriter(this.logFile))
{
    // Write additional data out...
}

Without having to open the file twice?

I can't seem to make the StreamReader not-dispose my stream. I don't want to just let it go out of scope, either. Then the garbage collector will eventually call the Dispose, killing the stream.

C# Solutions


Solution 1 - C#

.NET 4.5 will finally fix this problem with a new constructors on StreamReader and StreamWriter that take a leaveOpen parameter:

StreamReader(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool leaveOpen)

StreamWriter(Stream stream, System.Text.Encoding encoding, int bufferSize, bool leaveOpen)

Solution 2 - C#

> I don't want to just let it go out of scope, either. Then the garbage collector will eventually call the Dispose, killing the stream.

Garbage collector will call the Finalize method (destructor), not the Dispose method. The finalizer will call Dispose(false) which will not dispose the underlying stream. You should be OK by leaving the StreamReader go out of scope if you need to use the underlying stream directly. Just make sure you dispose the underlying stream manually when it's appropriate.

Solution 3 - C#

You could use the NonClosingStreamWrapper class from Jon Skeet's MiscUtil library, it serves exactly that purpose

Solution 4 - C#

You could create a new class which inherits from StreamReader and override the Close method; inside your Close method, call Dispose(false), which as Mehrdad pointed out, does not close the stream. Same applies to StreamWriter, of course.

However, it seems like a better solution would simply be to hold onto the StreamReader and StreamWriter instances as long as you may need them. If you're already planning to keep the stream open, you might as well keep a StreamReader and StreamWriter open also. If you use StreamWriter.Flush and Stream.Seek correctly, you should be able to make this work even when doing both reading and writing.

Solution 5 - C#

Just remove the using-Block. You don't have to Dispose() the StreamReader if you don't want to do Dispose() the stream, I think.

Solution 6 - C#

Use another constructor overload where you can specifu a "leaveOpen" parameter to "true"

Solution 7 - C#

I always use something like this: (it also uses the leaveOpen argument)

public static class StreamreaderExtensions
{
    public static StreamReader WrapInNonClosingStreamReader(this Stream file) => new StreamReader(file, Encoding.UTF8, true, 1024, true);
}

Usage:

using (var reader = file.WrapInNonClosingStreamReader())
{
     ....
}

Solution 8 - C#

I was able to use leaveOpen parameter without specifying all the constructor params (encoding or buffer size) like this:

using var streaReader = new StreamReader(stream, leaveOpen: true);

Solution 9 - C#

Close it yourself in a try/finally clause when you're done with it.

var sr = new StreamReader();
try {
    //...code that uses sr
    //....etc
}
finally
{
    sr.Close();
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJohn GietzenView Question on Stackoverflow
Solution 1 - C#Simon BuchanView Answer on Stackoverflow
Solution 2 - C#mmxView Answer on Stackoverflow
Solution 3 - C#Thomas LevesqueView Answer on Stackoverflow
Solution 4 - C#AaronView Answer on Stackoverflow
Solution 5 - C#eWolfView Answer on Stackoverflow
Solution 6 - C#HANiSView Answer on Stackoverflow
Solution 7 - C#Nick N.View Answer on Stackoverflow
Solution 8 - C#JakubView Answer on Stackoverflow
Solution 9 - C#Mike AtlasView Answer on Stackoverflow