如果我使用 FileStream 创建 StreamReader,当我关闭 FileStream 时 StreamReader 会关闭还是我也需要关闭 StreamReader?
public void ReadFile()
{
var file = new FileStream("c:\file.txt", FileMode.Open, FileAccess.Read);
var reader = new StreamReader(file);
try
{
txtFile.Text = reader.ReadToEnd();
}
catch (Exception)
{
throw;
}
finally
{
file.Close();
}
}
基本上是的。您实际上不必关闭 StreamReader。如果你这样做,它所做的就是关闭底层流。
@Bruno 关于关闭最外层的包装器提出了一个很好的观点。关闭最外层流并让它关闭底层流以确保正确释放所有资源是一种很好的做法。
来自反射器...
public class StreamReader : TextReader
{
public override void Close()
{
this.Dispose(true);
}
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);
}
}
}
}
没有。您应该关闭
reader
。实际上,这可能不会出现任何问题,但是 StreamReader
可能会增加一些可能需要清理的开销。所以你应该总是关闭最上面的包装器。
您也可以只使用 File.ReadAllText 方法:
txtFile.Text = File.ReadAllText(@"c:\file.txt");
您不需要关闭 StreamReader,因为它不拥有任何非托管资源。关闭 FileStream 就足够了。你可以像这样用
using
重写你的代码:
public void ReadFile()
{
using (var file = new FileStream("c:\file.txt", FileMode.Open, FileAccess.Read))
{
txtFile.Text = new StreamReader(file).ReadToEnd();
}
}
一般来说,如果您有疑问,最好是安全并在使用完所有 IDisposable 对象后处置它们。
public void ReadFile()
{
using (FileStream file = new FileStream("c:\file.txt", FileMode.Open, FileAccess.Read))
{
using (StreamReader streamReader = new StreamReader(file))
{
txtFile.Text = streamReader.ReadToEnd();
}
}
}
没有。最好的办法是以打开它们的相反顺序关闭它们。
在我看来,总体上执行此操作的最佳方法是让 FileStream 仅关闭自身。它并不隐含地知道存在于自身之上的层中的任何东西,因此它做任何会影响那些更高层的事情实际上是一个错误。
话虽如此,更高级别的构造也不应该公理化地假设任何提供的底层,或者如果他们这样做,他们应该明确地这样做:
1)如果它是从现有流创建的,那么更高级别的构造应该能够关闭底层流的INDEPENDENTLY(实际上只是处理它分配给自己使用的任何资源),或者关闭包括 底层流。这些应该是两个不同的函数调用,例如 Close() 和 CloseSelf()(如果要以与现有代码向后兼容的方式实现)。
2) 如果它不是从现有流创建的(也就是说,构造函数必须创建底层流),那么关闭更高级别的构造应该也强制关闭底层流,因为在这种情况下底层流是更高层次结构的隐含部分。在这种情况下,CloseSelf() 将简单地调用 Close()。
按原来的方式实现这些类似乎很浪费。如果您计划将同一个文件用于(作为示例)串行输入和串行输出,如果您希望获得对子类的更高级别功能的访问权限,那么系统实际上会强制您将其视为两个不同的实体。您的替代方案是坚持较低级别的构造并自己实现较高级别的功能 - 有效地重新实现您自己的已经存在的后代类的特殊版本。
如果按上述方式完成,典型的功能将像现在一样易于实现,但对于更复杂的应用程序,人们将保留在文件上放置单个锁并在需要时根据需要重新调整用途的能力而不是必须放弃锁和所有相关资源,然后立即重新分配它们——在没有任何正当理由的情况下向系统添加开销和内存碎片。
但在现有条件下,正确的事情是明确的。不能假定 FileStream 对它成为其一部分的任何对象一无所知,因此您必须关闭最外层的封闭构造。正如 Bruno 等人所指出的那样,无论它是否以任何一种方式工作,这都适用,并且出于他们给出的原因 - 兼容性。假设是最丑陋的错误的曾祖父。
有趣的是,关闭 StreamReader 或 writer 将影响拥有 FileStream 的读/写状态。这似乎意味着您不能先使用 StreamReader,然后使用相同的文件流使用 StreamWriter。