Can you keep a StreamReader from disposing the underlying stream? - c#

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.

.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)

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.

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

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.

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.

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

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())
{
....
}

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);

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();
}

Related

How to apply using-pattern with System.Func?

Usually I use a memory stream with the well known using pattern.
using(var mem = new MemoryStream(blob))
{
foo(mem);
}
No imagine a function bar(Func<Stream>) defined in a client library that I have to use. I could call it like this
bar(() => new MemoryStream(blob));
but then nobody is disposing the stream properly. How to work around it? Should Func be used with IDisposable types at all?
It seems like a poorly designed library.
If you know for a fact that the library does not dispose of the stream and it doesn't hold the Func<Stream> for later use, then you can do this:
using(var mem = new MemoryStream(blob))
{
bar(() => mem);
}

Disposing MemoryStreams and GZipStreams

I want to compress a ProtoBuffer object on serialisation and decompress on deserialisation. Unfortunatly, C# stdlib offers only compression routines that work on streams rather than on byte[], that makes it a bit unesseray more verbose than a function call. My Code so far:
class MyObject{
public string P1 {get; set;}
public string P2 {get; set;}
// ...
public byte[] Serialize(){
var builder = new BinaryFormat.MyObject.Builder();
builder.SetP1(P1);
builder.SetP2(P2);
// ...
// object is now build, let's compress it.
var ms = new MemoryStream();
// Without this using, the serialisatoin/deserialisation Tests fail
using (var gz = new GZipStream(ms, CompressionMode.Compress))
{
builder.Build().WriteTo(gz);
}
return ms.ToArray();
}
public void Deserialize(byte[] data)
{
var ms = new MemoryStream();
// Here, Tests work, even when the "using" is left out, like this:
(new GZipStream(new MemoryStream(data), CompressionMode.Decompress)).CopyTo(ms);
var msg = BinaryFormat.MachineInfo.ParseFrom(ms.ToArray());
P1 = msg.P1;
P2 = msg.P2;
// ...
}
}
When dealing with streams, it seems one has to manually take care of the disposal of the objects. I wonder why that is, I'd expect GZipStream to be fully managed Code. And I wonder If Deserialize works only by accident and if I should dispose the MemoryStreams aswell.
I know I could probably solve this problem by simply using a thrid party compression library, but that's somewhat besides the point of this question.
GZipStream needs to be disposed so it flushes it's final blocks of compression out of its buffer to its underlying stream, it also calls dispose on the stream you passed in unless you use the overload that takes in a bool and you pass in false.
If you where using the overload that did not dispose of the MemoryStream it is not as critical to have the MemoryStream be disposed because it is not writing its internall buffer anywhere. The only thing it does is set some flags and set a Task object null so it can be GCed sooner if the stream lifetime is longer than the dispose point.
protected override void Dispose(bool disposing)
{
try {
if (disposing) {
_isOpen = false;
_writable = false;
_expandable = false;
// Don't set buffer to null - allow TryGetBuffer, GetBuffer & ToArray to work.
#if FEATURE_ASYNC_IO
_lastReadTask = null;
#endif
}
}
finally {
// Call base.Close() to cleanup async IO resources
base.Dispose(disposing);
}
}
Also, although the comment says "Call base.Close() to cleanup async IO resources" the base dispose function from the Stream class does nothing at all.
protected virtual void Dispose(bool disposing)
{
// Note: Never change this to call other virtual methods on Stream
// like Write, since the state on subclasses has already been
// torn down. This is the last code to run on cleanup for a stream.
}
All that being said, when decompressing a GZipStream you can likely get away with not disposing it for the same reason as not disposing the MemoryStream, when decompressing it does not buffer bytes anywhere so there is no need to flush any buffers.

Do i need to Dispose Stream when i Pass it to IDisposable class?

I wrote a piece of code. I want to make sure that I am Disposing an Object in right way.
I have a Disposable Class like this
Which is used to read some data from unmanaged resource.
class MyFileReader : IDisposable
{
private readonly FileStream _stream;
public MyFileReader(FileStream stream)
{
_stream = stream;
}
public void Dispose()
{
_stream.Dispose();
}
}
Currently in my program I Dispose objects like this.
using (FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (MyFileReader reader = new MyFileReader(stream))
{
//...
}
}
This seems ok to me. later I have noticed That Classes are passed by reference so maybe if I dispose one of them there is no need to dispose the other one.
My question is Can i Do Something like this?
using (FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
{
MyFileReader reader = new MyFileReader(stream);
// Remove IDisposable from MyFileReader and stream will close after using.
}
Or this one?
FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
// stream will close after using.
using (MyFileReader reader = new MyFileReader(stream))
{
//...
}
Yes, you can write code like that.
But, no, you should not do that.
Your class looks like on of XxxxReader classes that by convention own the stream they read from. As result your MyFileReader class is expected to dispose the inner stream. You also normally expected to dispose each and every disposable object when you know that such object's lifetime is over.
Note that sometimes it lead to multiple Dispose calls on some objects (which should be expected by implementations of IDisposable). While it may sometimes lead to Code Analysis warning it is better than missing Dispose calls if one routinely tries to "optimize" number of calls to Dispose by skipping some.
Alternative approach is to expose method that reads content which by convention is not expected to take ownership of stream/reader like:
using(stream....)
{
var result = MyFileReader.ReadFrom(stream);
}
If MyFileReader is accessing some unmanaged resource and you need the Disponse method to be called explicitly after this code block, then you have to stick with your current implementation.
In the second implementation, the Dispose method will not be called for the MyFileReader object. (until you probably call it in the destructor which you don't know when that would be called)
If you do not like the nested using, then you can probably go with the second alternative and in the Dispose() method implementation of MyFileReader class, explicitly dispose the Stream. If this stream is only use by MyFileReader, then this is a good practice to have MyFileReader manage its lifecycle and dispose it.
Many framework stream-wrapping classes have constructor overloads with leaveOpen parameter that controls stream disposing behavior.
Examples include StreamReader, BinaryReader, GZipStream.
There is also property approach, SharpZipLib example:
using (var zip = new ZipInputStream(stream) { IsStreamOwner = false }) { ... }

Generic Stream that can call Dispose() method for another object after closing

Here is a very simple example how I can return a Stream to ASP.NET MVC:
public ActionResult DownloadData(...)
{
using(var lib = new SomeLibrary())
{
// do some stuff...
var stream = new MemoryStream();
lib.SaveAs(stream);
stream.Position = 0;
return File(stream, "contenttype", "filename");
}
}
The problem is that MemoryStream will be allocated in large heap object area and on 32 bit system it will cause OutOfMemoryException quite soon because of RAM fragmentation that will prevent allocation of a large memory block even if there is enough memory. On 64 bit systems this method is also quite slow.
What I want is just return a stream, similar to this
public ActionResult DownloadData(...)
{
using(var lib = new SomeLibrary())
{
// do some stuff...
return File(lib.Stream, "contenttype", "filename");
}
}
However then the using statement will call .Dispose() before my data is returned. If I remove the using statement completely, then the library will lock resources until garbage collector clean up memory.
I think the best solution will be to use a generic Stream that just copy the source stream and call .Dispose() at the end:
public ActionResult DownloadData(...)
{
var lib = new SomeLibrary()
try
{
// do some stuff...
var stream = new CopyStream(lib.Stream, lib);
return File(stream, "contenttype", "filename");
}
catch(Exception)
{
lib.Dispose();
throw;
}
}
The generic stream should call .Dispose() for the second parameter lib after closing.
Is there any existing implementation for such a Stream in .NET or NuGet?
Maybe i did not understand exactly what you need but in your case, there is no need to dispose the stream by yourself (with an explicit Dispose() call or with the using keyword).
The File helper method coming from ASP MVC controller is designed to return streams : It creates a FileStreamResult that is in charge of disposing the encapsulated stream and will do it when its job is done.
On this topic, you can find a far better and more detailed answer of Darin Dimitrov in here.

Why does a stream dispose when its writer is disposed?

Consider the following code:
using (var ms = new MemoryStream())
{
using(var writer = BinaryWriter(ms))
{
writer.Write(/*something*/);
writer.Flush();
}
Assert.That(ms.Length > 0); // Throws ObjectDisposedException
}
On the one hand, a disposable object should dispose of it's resources; I get that, but on the other hand, the object didn't create and doesn't own this resource, it was provided -> calling code should take responsibility for it... no?
I can't think of any other situations like this, but is it a consistent pattern in the framework for any class receiving disposable objects to dispose of them on its own dispose?
There is an implicit assumption that you will only have one writer per stream, so the writer assumes ownership of the stream for convenience - you then obly have one thing to clean up.
But I agree; this is not always true, and often inconvenient. Some implementations (DeflateStream, GZipStream, for example) allow you to choose. Otherwise the only real option is to inject a dummy stream between the writer and the underlying stream; IIRC there is a NonClosingStreamWrapper in Jon Skeet's "MiscUtil" library that does exactly this: http://www.yoda.arachsys.com/csharp/miscutil/
Usage would be something like:
using (var ms = new MemoryStream())
{
using(var noClose = new NonClosingStreamWrapper(ms))
    using(var writer = BinaryWriter(noClose))
    {
        writer.Write(/*something*/);
        writer.Flush();
    }
    Assert.That(ms.Length > 0);
}
I totally agree with you. This is not consistent behavior but it is how it has been implemented. There are comments at the end of the documentation about this behavior which is not very intuitive. All stream writers just take ownership of the underlying stream and dispose it. Personally I always nest my using statement like this:
using (var ms = new MemoryStream())
using(var writer = BinaryWriter(ms))
{
writer.Write(/*something*/);
}
so that a code like the one you put in the Assert shouldn't be written.
The right thing to have done would have been to have a constructor parameter for the streamwriter indicate whether the stream should be disposed when the constructor is. Given that Microsoft didn't do that, it may be good to define a NonDisposingStream(Of T as Stream) class which wraps a stream but does not pass a Dispose call to the wrapped stream. One could then pass a new NonDisposingStream to the constructor of a StreamWriter, and the underlying stream would be safe from disposal (it would be necessary, of course, to dispose of the stream yourself).
Having an object which can dispose of a passed-in object is useful. While such behavior doesn't coincide with the usual pattern of an object's creator handling its disposal, there are often situations where an object's creator will have no idea how long the object will actually be needed. For example, a method may be expected to create a new StreamWriter which uses a new Stream. The owner of the StreamWriter will know when it should be disposed, but may not know of the inner stream's existence. The creator of the inner stream will have no idea how long the outer StreamWriter will be used. Having ownership of the stream "handed off" to the StreamWriter solves the disposal problem in that particular (common) case.
I propose this wrapper class:
public class BetterStreamWriter : StreamWriter
{
private readonly bool _itShouldDisposeStream;
public BetterStreamWriter(string filepath)
:base(filepath)
{
_itShouldDisposeStream = true;
}
public BetterStreamWriter(Stream stream)
: base(stream)
{
_itShouldDisposeStream = false;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing && _itShouldDisposeStream);
}
}
Objects should not dispose stuff they didn't instantiate. If it's a file stream writer, it should dispose. If it's an external stream, it shouldn't.
Shouldn't have implemented opening file path in the first place. This violate single responsibility principle as the object both manages writing and lifetime of the file.

Categories