关于c#:处理streamreader会关闭流吗?

Does disposing streamreader close the stream?

我正在向要写入的方法发送流,在这些方法中,我使用的是二进制读卡器/wrtier。当读写器被using释放,或者只是当它没有被引用时,流是否也关闭了??

我会发送一个BinaryReader/Writer,但我也在使用一个StreamReader(也许我应该绕过它)。我只是把它用于getline和readline)。如果每次编写器/读卡器关闭流时都将其关闭,那么这将非常麻烦。


是的,当您调用Dispose时,StreamReaderStreamWriterBinaryReaderBinaryWriter都会关闭/处理它们的底层流。但是,如果读写器只是垃圾收集,那么它们不会处理流-您应该始终处理读写器,最好使用using语句。(实际上,这些类都没有终结器,也不应该有终结器。)

就我个人而言,我也更喜欢流有一个using语句。您可以不使用大括号非常整齐地嵌套using语句:

1
2
3
4
using (Stream stream = ...)
using (StreamReader reader = new StreamReader(stream, Encoding.Whatever))
{
}

尽管流的using语句有点多余(除非StreamReader构造函数抛出异常),但我认为最好的做法是,如果去掉StreamReader,稍后直接使用流,就已经有了正确的处理语义。


这是一个旧的,但我今天想做一些类似的事情,发现事情已经改变了。由于.NET 4.5,有一个leaveOpen参数:

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

唯一的问题是,为其他参数设置什么并不十分明显。以下是一些帮助:

从streamreader构造函数(stream)的msdn页:

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

只剩下detectEncodingFromByteOrderMarks,根据源代码判断,它就是true

1
2
3
4
5
6
7
public StreamReader(Stream stream)
        : this(stream, true) {
}

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

如果其中一些默认值是公开的,或者参数是可选的,这样我们就可以指定所需的参数。


是的,的确如此。您可以通过使用Reflector查看实现来验证这一点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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);
        }
    }
}

已经晚了六年了,但也许这能帮上忙。

streamreader在释放连接时确实会关闭连接。但是,对streamreader/streamwriter使用(stream stream=…)…"可能会导致流被释放两次:(1)当streamreader对象被释放时(2)以及当使用流块的流关闭时。当运行vs的代码分析时,这会导致CA2202警告。

另一个直接从CA2202页面获取的解决方案是使用Try/Finally块。设置正确,这将只关闭一次连接。

靠近CA2202底部,Microsoft建议使用以下功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Stream stream = null;
try
{
    stream = new FileStream("file.txt", FileMode.OpenOrCreate);
    using (StreamWriter writer = new StreamWriter(stream))
    {
        stream = null;
        // Use the writer object...
    }
}
finally
{
    if(stream != null)
        stream.Dispose();
}

而不是。。。

1
2
3
4
5
6
// Generates a CA2202 warning
using (Stream stream = new FileStream("file.txt", FileMode.Open))
using (XmlReader reader = new XmlReader (stream))
{
    // Use the reader object...
}


对。对调用Dispose()和IDisposable(这是"using"所做的)应使对象清除其所有资源。这包括流刷新和关闭它们的文件描述符。

如果在您的案例中,您希望将它传递给其他方法,那么您需要确保这些方法不会在using块中进行读/写操作。


如果需要,解决此问题的一个简单方法是重写StreamWriter类的Dispose方法。有关如何操作的代码,请参阅我在此处的文章:

是否。释放streamwriter会关闭基础流?


通过"using"关键字或显式调用Dispose释放的流