Does disposing streamreader close the stream?
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.
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.
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);
}
}
}
Six years late but maybe this might help someone.
StreamReader does close the connection when it is disposed. However, "using (Stream stream = ...){...}" with StreamReader/StreamWriter can result in the Stream being disposed of twice: (1) when the StreamReader object is disposed (2) and when the Stream using block closes. This results in a CA2202 warning when running VS's code analysis.
Another solution, taken directly from the CA2202 page, is to use a try/finally block. Setup correctly, this will only close the connection once.
Near the bottom of CA2202, Microsoft recommends to use the following:
Stream stream = null;
try
{
stream = new FileStream("file.txt", FileMode.OpenOrCreate);
using (StreamWriter writer = new StreamWriter(stream))
{
stream = null;
// Use the writer object...
}
}
finally
{
stream?.Dispose();
}
instead of...
// Generates a CA2202 warning
using (Stream stream = new FileStream("file.txt", FileMode.Open))
using (XmlReader reader = new XmlReader (stream))
{
// Use the reader object...
}
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.