我是否需要关闭java.io包的Reader装饰器?

时间:2011-04-29 10:34:33

标签: java io

我需要解析一个对象,我需要将我收到的Reader包装到PushbackReader中。在任何情况下我是否需要关闭PushbackReader,或者它是否足够安全以使其保持打开状态,因为它是基础读者(我没有打开)

public static MyObject parse(Reader reader) throws IOException, ParseException {
  PushbackReader pReader = new PushbackReader(reader, PUSHBACK_SIZE);
  try {
    return parseMyObject(pReader);
  } finally {
    pReader.close();
  }
}

或仅仅写下以下内容足够安全:

public static MyObject parse(Reader reader) throws IOException, ParseException {
  return parseMyObject(new PushbackReader(reader, PUSHBACK_SIZE));
}

有关信息,这是我如何调用我的解析器:

BufferedReader reader = new BufferedReader(...);
try {
  while (...) {
    list.add(MyObjectParser.parse(reader));
  }
} catch (IOException e) {
  throw new RuntimeException("Could not read the stream", e);
} catch (ParseException e) {
  throw new ParseRuntimeException("Could not parse the stream", e);
} finally {
  // No need for null check.
  reader.close();
}

3 个答案:

答案 0 :(得分:4)

如果被叫方将关闭基础close(),则无需在PushbackReader上调用ReaderPushbaseReader只是一个包含缓冲区的包装器,当你完成它时会被垃圾收集。在其上调用close()将关闭基础Reader,如果您希望该方法关闭它,则需要保留它。

更新:根据您的代码,您似乎无法在close()上致电PushbackReader,因为它也会关闭您的基础Reader。如果你这样做,我可以看到,下一次迭代应该失败,关于流被关闭的例外。例如。这个例子失败了:

BufferedReader reader = new BufferedReader(new StringReader("foo"));
new PushbackReader(reader).close();
reader.read(); // IOException: Stream closed

答案 1 :(得分:1)

如果你还记得几个关键点,那就太复杂了:

  • 可以多次关闭一个流/读者/写入器。第二次(或后续)关闭无效。
  • 流包装器(PushBackReaderBufferedReader等。)执行在包装器关闭时关闭基础流。
  • 垃圾收集器通常会自动关闭流,除非流拥有OS资源(文件描述符,套接字等)。
  • 通常,流的创建者(使用try - finally块)在完成后关闭流,例如

Reader reader = new FileReader(file);
try {
    parse(reader);
} finally {
    reader.close();
}

因此,作为一般规则,parse()不应该关闭读者,除非它有充分理由这样做(例如,IOException已使流处于不确定状态),以防来电者希望将流用于别的东西。

如果parse在完成流程后关闭了流,那么可能不是世界末日,但如果确实如此,那么你一定要记录这个事实。

答案 2 :(得分:0)

最佳做法是始终关闭读者 - 如果它们碰巧是其他读者的包装,那么他们应该将关闭操作级联到它们。

在您的代码段中,只需确定责任所在的位置即可。有人应该关闭阅读器,parse方法或parseMyObject方法。我更喜欢parse方法,因为那时代码更具可读性 - 创建/打开阅读器的方法与关闭它的方法相同。
(否则你会遇到奇怪的情况 - 其他人可以使用parseMyObject,然后突然惊讶于它关闭了读者的论点)

<强>更新

现在我看到了你的问题的更新,这归结为在循环中接受一个reader参数,然后多次包装它。我建议你重构代码,这样你只需用PushbackReader包装一次。或者将阅读器的初始化代码移动到内部方法中。