C# 您能否阻止StreamReader处理底层流?

C# 您能否阻止StreamReader处理底层流?,c#,file-io,C#,File Io,有没有办法做到这一点: this.logFile = File.Open("what_r_u_doing.log", FileMode.OpenOrCreate, FileAccess.ReadWrite); using(var sr = new StreamReader(this.logFile)) { // Read the data in } // ... later on in the class ... this.logFile = File.Open("what_r_u

有没有办法做到这一点:

this.logFile = File.Open("what_r_u_doing.log", FileMode.OpenOrCreate, FileAccess.ReadWrite);

using(var sr = new StreamReader(this.logFile))
{
    // Read the data in
}

// ... later on in the class ...

this.logFile = File.Open("what_r_u_doing.log", FileMode.OpenOrCreate, FileAccess.ReadWrite);

using(var sw = new StreamWriter(this.logFile))
{
    // Write additional data out...
}
不必打开文件两次


我似乎无法让StreamReader不处理我的流。我也不想让它超出范围。然后,垃圾收集器最终将调用Dispose,终止流。

完成后,请自己在
try
/
finally
子句中关闭它

var sr = new StreamReader();
try {
    //...code that uses sr
    //....etc
}
finally
{
    sr.Close();
}

只需移除使用块。我认为,如果不想对流执行Dispose()操作,则不必对StreamReader执行Dispose()

我也不想让它超出范围。然后垃圾收集器将最终调用Dispose,终止流


垃圾收集器将调用
Finalize
方法(析构函数),而不是
Dispose
方法。终结器将调用
Dispose(false)
,这将处理底层流。如果需要直接使用底层流,则可以将
StreamReader
退出范围。只要确保在适当的时候手动处理底层流。

您可以使用Jon Skeet的
非关闭流说话者
类,它正是为了这个目的

您可以创建一个从StreamReader继承的新类,并覆盖Close方法;在Close方法中,调用Dispose(false),正如Mehrdad指出的那样,它不会关闭流。当然,StreamWriter也是如此


但是,似乎更好的解决方案是,只要您需要,就保留StreamReader和StreamWriter实例。如果您已经计划让流保持打开状态,那么还可以让StreamReader和StreamWriter保持打开状态。如果正确使用StreamWriter.Flush和Stream.Seek,则即使在执行读写操作时,也应该能够执行此操作。

.NET 4.5最终将通过StreamReader和StreamWriter上采用leaveOpen参数的新构造函数解决此问题:

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

StreamWriter(Stream stream, System.Text.Encoding encoding, int bufferSize, bool leaveOpen)

使用另一个构造函数重载,您可以在其中将“leveopen”参数指定为“true”

我总是使用这样的方法: (它还使用
leaveOpen
参数)

用法:

using (var reader = file.WrapInNonClosingStreamReader())
{
     ....
}

我可以使用
leaveOpen
参数,而无需指定所有构造函数参数(编码或缓冲区大小),如下所示:

using var streaReader = new StreamReader(stream, leaveOpen: true);

问题是,它迫使我弄清楚要传递什么编码,以使StreamReader的行为与我使用
StreamReader(Stream)
构造函数打开它时的行为相同。因此,我仍然在使用“不要处理并希望我的同事没有人通过将StreamReader放入使用块来‘纠正’该方法”的方法:(@phoog:(在我的收件箱中)MSDN应该列出转发样式重载的默认值,例如
StreamReader(Stream)
说“此构造函数将编码初始化为UTF8Encoding,使用stream参数将BaseStream属性初始化为1024字节。”@SimonBuchan但我不必在程序中硬编码这些默认值。
StreamReader()
构造函数应该被修改为采用选项样式的类参数,比如
XmlReaderSettings
的工作方式。然后可以由框架管理默认值,并以非ABI中断和非硬烘焙的方式添加新参数。使用(var reader=StreamReader(OtherStream,System.Text.Encoding.UTF8,1024,true)){…}如果您想坚持默认值。comment Moved StreamReader的源代码是。您可以使用Microsoft默认值作为中间参数:Encoding=UTF8,detectedEncodingFromByteOrderMarks=true,bufferSize=4096。然后设置leaveOpen=true。但是将来是否有可能修改StreamReadero保留一些非管理的资源,开始实现终结器,然后当超出范围时,在垃圾收集器终结流时随机关闭流?或者我们应该假设,既然现在不发生这种情况,它永远不会发生?根据引用源,这似乎是一个好的答案。这相当于调用流无参数构造函数,但将leaveOpen指定为true。“没有给定与所需的形式参数“encoding”相对应的参数。(.NET 4.8)
using var streaReader = new StreamReader(stream, leaveOpen: true);