Does disposing streamreader close the stream?

2019-01-01 15:04发布

I am sending a stream to methods to write on, and in those methods I am using a binary reader/wrtier. When the reader/writer gets disposed, either by using or just when it is not referenced, is the stream closed as well??

I would send a BinaryReader/Writer, but I am using a StreamReader too (maybe I should go around that. I am only using that for GetLine and ReadLine). This is quite troublesome if it closes the stream each time a writer/reader gets closed.

7条回答
听够珍惜
2楼-- · 2019-01-01 15:34

Yes. Calling Dispose() on and IDisposable (which "using" does) should make an object clean up all of its resources. This includes streams flushing and closing their file descriptors.

If, in your case, you want to pass it in to other methods, then you need to make sure that those methods do not do their reading/writing in a using block.

查看更多
其实,你不懂
3楼-- · 2019-01-01 15:36

the stream disposed either by "using" keyword or calling dispose explicitly

查看更多
牵手、夕阳
4楼-- · 2019-01-01 15:45

This is an old one, but I wanted to do something similar today and found that things have changed. Since .net 4.5, there is a leaveOpen argument:

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

The only problem is that it is not entirely obvious what to set for the other parameters. Here is some help:

From the msdn page for StreamReader Constructor (Stream):

This constructor initializes the encoding to UTF8Encoding, the BaseStream property using the stream parameter, and the internal buffer size to 1024 bytes.

That just leaves detectEncodingFromByteOrderMarks which judging by the source code is true

public StreamReader(Stream stream)
        : this(stream, true) {
}

public StreamReader(Stream stream, bool detectEncodingFromByteOrderMarks)
        : this(stream, Encoding.UTF8, detectEncodingFromByteOrderMarks, DefaultBufferSize) {
}

It would be nice if some of those defaults were exposed or if the arguments were optional so that we could just specify the ones that we want.

查看更多
何处买醉
5楼-- · 2019-01-01 15:49

An easy way to fix this if you need to is to override the StreamWriter classes Dispose method. See my post here for the code on how to do it:

Does .Disposing a StreamWriter close the underlying stream?

查看更多
泪湿衣
6楼-- · 2019-01-01 15:55

Yes, it does. You can verify this by looking at the implementation with Reflector.

protected override void Dispose(bool disposing)
{
    try
    {
        if ((this.Closable && disposing) && (this.stream != null))
        {
            this.stream.Close();
        }
    }
    finally
    {
        if (this.Closable && (this.stream != null))
        {    
            this.stream = null;    
            this.encoding = null;
            this.decoder = null;
            this.byteBuffer = null;
            this.charBuffer = null;
            this.charPos = 0;
            this.charLen = 0;
            base.Dispose(disposing);
        }
    }
}
查看更多
余欢
7楼-- · 2019-01-01 15:56

Yes, StreamReader, StreamWriter, BinaryReader and BinaryWriter all close/dispose their underlying streams when you call Dispose on them. They don't dispose of the stream if the reader/writer is just garbage collected though - you should always dispose of the reader/writer, preferrably with a using statement. (In fact, none of these classes have finalizers, nor should they have.)

Personally I prefer to have a using statement for the stream as well. You can nest using statements without braces quite neatly:

using (Stream stream = ...)
using (StreamReader reader = new StreamReader(stream, Encoding.Whatever))
{
}

Even though the using statement for the stream is somewhat redundant (unless the StreamReader constructor throws an exception) I consider it best practice as then if you get rid of the StreamReader and just use the stream directly at a later date, you'll already have the right disposal semantics.

查看更多
登录 后发表回答