14

从文本文件读取时,通常会创建 aFileReader然后将其嵌套在BufferedReader. 阅读完毕后,我应该关闭两个阅读器中的哪一个?有关系吗?

FileReader fr = null;
BufferedReader br = null;
try
{
    fr = new FileReader(fileName);
    br = new BufferedReader(fr);
    // ...
}
finally
{
    // should I close fr or br here?
}

当谈到异常安全时,我有点偏执。当BufferedReader构造函数抛出异常时会发生什么?它会关闭嵌套阅读器吗?还是保证不扔?

4

5 回答 5

10

通常,close()在最外层的流包装器会调用close()被包装的流。但是,如果您认为构造函数可能会抛出异常,请自由使用Closeable接口。

FileReader fr = new FileReader(fileName);
Closeable res = fr;
try {
    BufferedReader br = new BufferedReader(fr);
    res = br;
} finally {
    res.close();
}

因此,即使 JVM 用完缓冲区的堆空间并抛出错误,您也不会泄漏文件句柄。

对于 Java 7 及更高版本,请使用 try-with-resources:

try (FileReader fr = new FileReader(fileName);
    BufferedReader br = new BufferedReader(fr)) {
  // do work
}
于 2011-02-05T19:37:25.093 回答
0

只关闭BufferedReader就足够了,因为它包装了FileReader. 如果您查看源代码BufferedReader您会看到该close方法关闭了包装的流。

于 2011-02-05T19:30:32.897 回答
0

在 finally 块中关闭 BufferedReader。

于 2011-02-05T19:31:31.470 回答
0

如果调用 BufferedReader 的 close 方法,BufferedReader 将调用 FileReader 的 close 方法。因此,两个 close 方法都被调用。更准确地说,BufferedReader 除了调用 FileReader 的 close 方法之外什么都不做。因此,这根本不重要。虽然我认为调用 BufferedReader 的 close 方法也是一种好习惯。

于 2011-02-05T19:38:06.117 回答
0

没有什么是保证不扔的。因为缓冲区已分配,它可能会抛出 OutOfMemoryError。我通常将我的代码分成两部分:获取资源,然后使用资源。每个部分通常都有独特的清理需求

这是说明的代码:

// Acquire resources section.

final FileReader fr = new FileReader( fileName );

BufferedReader br = null;

try
{
    br = new BufferedReader(fr);
}
finally
{
    if ( br == null )
    {
        // Note that you are closing the fr here
        fr.close( );
    }
}

// Use resources section
try
{
    // ... use br
}
finally
{
    // Now that br is safely constructed, just all its close
    br.close( );
}

我同意你的看法,没有什么比在长时间运行的服务器应用程序中静默释放文件处理程序更有价值的了。

于 2011-02-05T21:00:54.840 回答