Ars*_*nko 10 c# idisposable stream streamreader
我需要从开始到结束两次读取一个流.
但是以下代码抛出ObjectDisposedException: Cannot access a closed file异常.
string fileToReadPath = @"<path here>";
using (FileStream fs = new FileStream(fileToReadPath, FileMode.Open))
{
using (StreamReader reader = new StreamReader(fs))
{
string text = reader.ReadToEnd();
Console.WriteLine(text);
}
fs.Seek(0, SeekOrigin.Begin); // ObjectDisposedException thrown.
using (StreamReader reader = new StreamReader(fs))
{
string text = reader.ReadToEnd();
Console.WriteLine(text);
}
}
Run Code Online (Sandbox Code Playgroud)
为什么会这样?什么是真的处置?为什么操纵StreamReader会以这种方式影响相关的流?期望可以多次读取可搜索流是不合逻辑的,包括几个StreamReaders?
Han*_*ant 16
发生这种情况是因为StreamReader接管了流的"所有权".换句话说,它使自己负责关闭源流.一旦您的程序调用Dispose或Close(using在您的情况下保留语句范围),它也将处置源流.打电话给fs.Dispose()你的情况.因此离开第一个using块后文件流已经死了.这是一致的行为,.NET中包含另一个流的所有流类都以这种方式运行.
有一个构造函数StreamReader允许说它不拥有源流.但是,无法从.NET程序访问它,构造函数是内部的.
在这种特殊情况下,您可以通过不使用using-statement来解决问题StreamReader.然而,这是一个相当毛茸茸的实现细节.肯定有更好的解决方案可供您使用,但代码太合成了,无法提出真正的解决方案.
目的Dispose()是在完成流后清理资源.读者影响流的原因是因为读者只是过滤流,因此除了在链接对源流的调用的上下文中之外,处理读取器没有任何意义.
要修复代码,请在整个时间内使用一个阅读器:
using (FileStream fs = new FileStream(fileToReadPath, FileMode.Open))
using (StreamReader reader = new StreamReader(fs))
{
string text = reader.ReadToEnd();
Console.WriteLine(text);
fs.Seek(0, SeekOrigin.Begin); // ObjectDisposedException not thrown now
text = reader.ReadToEnd();
Console.WriteLine(text);
}
Run Code Online (Sandbox Code Playgroud)
编辑以解决以下评论:
在大多数情况下,您不需要像在代码中那样访问基础流(fs.Seek).在这些情况下,StreamReader链接其对底层流的调用这一事实允许您通过不使用usings流的语句来节省代码.例如,代码看起来像:
using (StreamReader reader = new StreamReader(new FileStream(fileToReadPath, FileMode.Open)))
{
...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6626 次 |
| 最近记录: |