【问题标题】:Do I need to close InputStream after I close the Reader关闭阅读器后是否需要关闭 InputStream
【发布时间】:2010-09-02 15:59:19
【问题描述】:

我想知道,在我关闭阅读器后是否需要关闭 InputStream?

try {
    inputStream = new java.io.FileInputStream(file);
    reader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
} catch (Exception exp) {
    log.error(null, exp);
} finally {
    if (false == close(reader)) {
        return null;
    }
    // Do I need to close inputStream as well?
    if (false == close(inputStream)) {
        return null;
    }
}

【问题讨论】:

  • 请使用if (!close(reader) 而不是if (false == close(reader))
  • @Jacob Tomaw - 为什么?!我的视力很差。 “false”比“!”占用更多的屏幕空间。这至少会让我更具可读性。
  • @Yan Cheng CHEOK 它的风格很差,而且很难让下一个人阅读您的代码。如果您看不到 !,则需要增加计算机的字体大小或戴上更坚固的眼镜,而不是创建自己的编码约定。
  • @bwawok 或将if (!check) { thing(); return; } otherthing(); 重新排列为if (check) { otherthing() } else { thing(); }
  • 哦,returnfinally 中?啊啊啊啊啊啊啊!!!

标签: java


【解决方案1】:

不,你不必这样做。

由于 Java 中用于流的装饰器方法可以通过将它们附加到其他流来构建新的流或读取器,这将由 InputStreamReader 实现自动处理。

如果您查看它的来源InputStreamReader.java,您会看到:

private final StreamDecoder sd;

public InputStreamReader(InputStream in) {
  ...
  sd = StreamDecoder.forInputStreamReader(in, this, (String)null);
  ...
}

public void close() throws IOException {
  sd.close();
}

所以关闭操作实际上关闭了流读取器底层的InputStream

编辑:我想确保StreamDecoder close 也适用于输入流,敬请期待。

检查过,StreamDecoder.java

void implClose() throws IOException {
  if (ch != null)
    ch.close();
  else
    in.close();
}

在调用 sd 的 close 时调用。

【讨论】:

  • 每个具体 StreamDecoders 的代码也会关闭调用 sd.close() 的底层输入流 ;-)
  • 如果我关闭 inputStream 有什么坏处吗?
  • 您是否发现它明确地写在了文档中?我不确定这是否是所有 Java 实现的约束。 @Yan Cheng CHEOK:如果在关闭阅读器后关闭输入流,是没有坏处的。
  • 但它不会在finally 中关闭它,对吧?所以可能不会在异常中关闭它?看源代码很危险,你应该只看文档。
  • @Viven Barousse:“关闭流并释放与之关联的任何系统资源。” -- java.io.Reader JavaDoc for close()
【解决方案2】:

从技术上讲,关闭Reader 将关闭InputStream。但是,如果在打开 InputStream 和创建 Reader 之间失败,您仍应关闭 InputStream。如果您关闭 InputStream [资源],则没有充分的理由关闭 Reader [装饰器]。还有一些流行的错误,关闭装饰器可能会在关闭装饰器之前引发异常。所以:

Resource resource = acquire();
try {
    Decorator decorated = decorate(resource);
    use(decorated);
} finally {
    resource.release();
}

需要注意一些并发症。由于它们的实现,一些装饰器实际上可能包含本机资源。输出装饰器通常需要刷新,但仅在满意的情况下(所以在 try 而不是 finally 块中)。

【讨论】:

  • 如果Decorator 是例如BufferedWriter,则会失败。没有明确记录程序员应该在使用后显式调用flush()
  • @BalusC 我很困惑。 BufferedWriter API 文档的第一行说它缓冲字符。
  • BufferedWriter(已装饰)将在close() 上使用flush()。例如,FileWriter(资源)不这样做。因此,当您仅关闭 FileWriter 时,您将面临未刷新字符的风险
  • @BalusC 正如我在回答中所说,通常需要刷新输出装饰器。它们是一种不寻常的资源。 FileWriter 是一场灾难。
  • 您能否在您的回答中详细说明“装饰器实际上可能包含本机资源,因为它们的实现”(也许还将“并发症”部分格式化为列表)。非常有用+1
【解决方案3】:

如果您close() 读者,则不必关闭流。

关闭流并释放与 它。一旦流被关闭,进一步 read(), ready(), mark(), reset() 或 skip() 调用将引发 IOException。关闭一个 之前关闭的流无效。

【讨论】:

    【解决方案4】:

    不,读者不会关闭底层的 InputStream

    【讨论】:

      【解决方案5】:

      根据源嗅探,阅读器关闭其底层输入流。根据 javadoc,当调用 reader.close() 时,InputStreamReader 会“关闭流”。

      我不确定当您执行 reader.close() 时是否有任何 Reader 必须关闭其源代码。我认为这很重要,因此您的代码可以使用阅读器,无论它是什么具体类型。

      无论如何,强制执行是有道理的。

      【讨论】:

        猜你喜欢
        • 2021-02-10
        • 2012-03-23
        • 2019-01-20
        • 2021-12-12
        • 2018-07-15
        • 1970-01-01
        • 2022-11-12
        • 2012-01-11
        • 1970-01-01
        相关资源
        最近更新 更多