为什么部署StreamReader会导致流不可读?我需要从头到尾读两次流。但是下面的代码抛出ObjectDisposedException:Cannotaccessaclosedfileexception。字符串fileToReadPath=@"";使用(FileStreamfs=newFileStream(fileToReadPath,FileMode.Open)){使用(StreamReaderreader=newStreamReader(fs)){stringtext=reader.ReadToEnd();控制台.WriteLine(文本);}fs.Seek(0,SeekOrigin.Begin);//抛出ObjectDisposedException。使用(StreamReaderreader=newStreamReader(fs)){stringtext=reader.ReadToEnd();控制台.WriteLine(文本);}}为什么?所以?真正处理掉的是什么?为什么操作StreamReader会以这种方式影响关联的流?期望一个可搜索流可以被多次读取(包括多个StreamReader)是不合逻辑的吗?发生这种情况是因为StreamReader接管了流的“所有权”。换句话说,它让自己负责关闭源流。一旦您的程序调用Dispose或Close(在您的情况下保持using语句范围),它也将处理源流。在您的情况下调用fs.Dispose()。所以文件流在离开第一个using块后就死了。这是一致的行为,.NET中包含另一个流的所有流类都以这种方式运行。StreamReader有一个构造函数,允许它说它不拥有源流。但是,它不能从.NET程序访问,构造函数是内部的。在这种特殊情况下,您可以通过不使用StreamReader的using语句来解决问题。然而,这是一个相当棘手的实现细节。肯定有更好的解决方案可供您使用,但代码过于综合,无法提供真正的解决方案。Dispose()的目的是在流完成后清理资源。读取器影响流的原因是因为读取器只是过滤流,所以处理读取器没有意义,除非在链接调用源流的上下文中。要修复代码,请始终使用一个阅读器:using(FileStreamfs=newFileStream(fileToReadPath,FileMode.Open))控制台.WriteLine(文本);fs.Seek(0,SeekOrigin.Begin);//现在不抛出ObjectDisposedExceptiontext=reader.ReadToEnd();控制台.WriteLine(文本);编辑以解决以下评论:在大多数情况下接下来,您不需要像在代码中那样访问基础流(fs.Seek)。在这些情况下,StreamReader的调用链接到基础流这一事实允许您通过不使用usings语句来保存代码。例如,代码如下所示:using(StreamReaderreader=newStreamReader(newFileStream(fileToReadPath,FileMode.Open))){...}Using定义了一个范围,对象将放置在该范围之外,从而消耗ObjectDisposedException。您无法访问此块之外的StreamReader的内容。我同意你的问题。这种有意的副作用的最大问题是开发人员不理解它并盲目地遵循使用StreamReader的“最佳实践”。但是当它存在于一个长期存在的对象的属性上时,它会导致一些非常难以追踪的错误,我见过的最好的(最坏的?)例子是使用(varsr=newStreamReader(HttpContext.Current.Request.InputStream)){body=sr.ReadToEnd();}开发人员不知道InputStream现在会在未来任何预期的地方使用。显然,一旦您了解了内部结构,您就会知道避免使用,只需阅读并重置位置即可。但我认为API设计的一个核心原则是避免副作用,尤其是不要破坏你正在处理的数据。被认为是“阅读器”的类在“使用”它时没有清理它读取的数据的固有内容。处理Reader应该释放对Stream的任何引用,而不是清除Stream本身。我唯一能想到的就是不得不做出选择,因为读者正在改变Stream的其他内部状态,比如搜索指针的位置,并且他们假设如果你正在使用它,你'故意做每件事。另一方面,就像在您的示例中一样,如果您正在创建一个Stream,则该流本身将被使用,但是如果您正在读取一个在您的即时方法之外创建的Stream,那么代码将肆意清除数据。我所做的并告诉我们的开发人员在不显式创建Stream实例的情况下读取代码是...//savepositionbeforereadinglongposition=theStream.Position;theStream.Seek(0,SeekOrigin.Begin);//DONOTputthisStreamReaderinausing,StreamReader.Dispose()清除流StreamReadersr=newStreamReader(theStream);字符串内容=sr.ReadToEnd();theStream.Seek(位置,SeekOrigin.Begin);(抱歉,我将此添加为答案,不适合发表评论,我想更多地讨论框架的设计决策)父级上的Dispose()将Dispose()所有拥有的流。不幸的是,流没有Detach()方法,因此您必须在此处创建一些解决方法。我不知道为什么,但您可以不用管StreamReader。这样,即使收集了StreamReader,您的基础流也不会被释放。以上是C#学习教程:为什么部署StreamReader会导致流不可读?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
