你能让StreamReader不要处理底层流吗?

时间:2009-12-07 19:19:07

标签: 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_doing.log", FileMode.OpenOrCreate, FileAccess.ReadWrite);

using(var sw = new StreamWriter(this.logFile))
{
    // Write additional data out...
}

无需打开文件两次?

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

9 个答案:

答案 0 :(得分:67)

.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)

答案 1 :(得分:46)

  

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

垃圾收集器将调用Finalize方法(析构函数),而不是Dispose方法。终结器将调用Dispose(false)处理基础流。如果您需要直接使用基础流,那么您应该将StreamReader超出范围。只需确保在适当的时候手动处理基础流。

答案 2 :(得分:15)

您可以使用Jon Skeet MiscUtil library中的NonClosingStreamWrapper课程,它正是为了这个目的而提供的

答案 3 :(得分:3)

您可以创建一个继承自StreamReader并覆盖Close方法的新类;在Close方法中,调用Dispose(false),就像Mehrdad指出的那样,不会关闭流。当然,同样适用于StreamWriter。

但是,只要您需要它们,似乎更好的解决方案就是保留StreamReader和StreamWriter实例。如果您已经计划保持流打开,那么您也可以打开StreamReader和StreamWriter。如果你正确使用StreamWriter.Flush和Stream.Seek,你应该能够在读写时都能使这个工作。

答案 4 :(得分:2)

只需删除using-Block。如果您不想对流进行Dispose(),则不必使用Dispose()StreamReader。

答案 5 :(得分:2)

使用另一个构造函数重载,您可以在其中指定" leaveOpen"参数to" true"

答案 6 :(得分:0)

完成后,请在try / finally子句中自行关闭。

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

答案 7 :(得分:0)

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

public static class StreamreaderExtensions
{
    public static StreamReader WrapInNonClosingStreamReader(this Stream file) => new StreamReader(file, Encoding.UTF8, true, 1024, true);
}

用法:

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

答案 8 :(得分:0)

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

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