简体   繁体   English

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

[英]Do I need to close a Reader decorator of the java.io package?

I need to parse an object and I need to wrap the Reader I receive into a PushbackReader.我需要解析 object 并且需要将收到的 Reader 包装到 PushbackReader 中。 Do I need to close the PushbackReader in any case or is it safe enough to leave it open since it's the underlying reader (that I didn't open) that我是否需要在任何情况下关闭 PushbackReader 或者是否足够安全以使其保持打开状态,因为它是底层阅读器(我没有打开)

With

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

Or is it safe enough to write only the following:或者只写以下内容是否足够安全:

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

For info, here's how I call my parser:有关信息,这是我调用解析器的方式:

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();
}

You don't need to call close() on the PushbackReader if the callee will be closing the underlying Reader .如果被调用者将关闭底层Reader ,则无需在PushbackReader上调用close() The PushbaseReader is just a wrapper with a buffer that'll be garbage collected when you're done with it. PushbaseReader只是一个带有缓冲区的包装器,当你完成它时会被垃圾收集。 Calling close() on it will close the underlying Reader , which you'll want to keep if you expect the method to be closing it.对其调用close()将关闭底层Reader ,如果您希望该方法将其关闭,您将希望保留它。

Update : Based on your code it looks like you can't call close() on the PushbackReader because it'll also close your underlying Reader .更新:根据您的代码,您似乎无法在PushbackReader上调用close() ,因为它也会关闭您的底层Reader The next iteration should fail with an exception about the stream being closed if you do that, from what I can see.从我所见,下一次迭代应该会失败,但如果你这样做,stream 将被关闭。 Eg this example fails:例如,此示例失败:

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

It's not too complicated if you remember a few key points:如果您记住几个关键点,这并不太复杂:

  • It's okay to close a stream/Reader/Writer more than once.多次关闭流/读取器/写入器是可以的。 A second (or subsequent) close has no effect.第二次(或后续)关闭无效。
  • Stream wrappers ( PushBackReader , BufferedReader etc.) do close the underlying stream when the wrapper is closed. Stream 包装器( PushBackReaderBufferedReader等)在包装器关闭关闭底层 stream 。
  • The garbage collector does not in general automatically close a stream unless the stream owns on OS resource (file descriptor, socket etc.)垃圾收集器通常不会自动关闭 stream 除非 stream 拥有操作系统资源(文件描述符、套接字等)
  • Typically the creator of a stream will (using a try - finally block) close the stream when finished with it, eg通常,stream 的创建者将(使用try - finally块)在完成 stream 后关闭它,例如

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

So as a general rule parse() should not close the reader unless it has a good reason to do so (eg an IOException has left the stream in an indeterminate state) in case the caller wishes to use the stream for something else.因此,作为一般规则parse()不应关闭阅读器,除非它有充分的理由这样做(例如, IOException使 stream 处于不确定状态),以防调用者希望将 stream 用于其他目的。

It's probably not the end of the world if parse closes the stream when it has finished with it, but if it does then you should definitely document the fact.如果parse完成后关闭 stream 可能不是世界末日,但如果确实如此,那么您绝对应该记录这一事实。

It is best practice that you always close your readers - if they happen to be wrappers to other readers then they should cascade the close operation to them.最好的做法是始终关闭您的阅读器 - 如果它们恰好是其他阅读器的包装器,那么他们应该将关闭操作级联给他们。

In your code snippet, it is just a matter of deciding where the responsibility resides.在您的代码片段中,只需决定责任所在的位置。 Someone should close the reader, either the parse method or the parseMyObject method.有人应该关闭阅读器,无论是parse方法还是parseMyObject方法。 I prefer the parse method because then the code is more readable - the same method that created/opened the reader is the one closing it.我更喜欢parse方法,因为这样代码更具可读性 - 创建/打开阅读器的相同方法是关闭它的方法。
(otherwise you get into strange situations - someone else can use the parseMyObject and then suddenly be surprised that it closed the reader argument) (否则你会遇到奇怪的情况——其他人可以使用parseMyObject然后突然惊讶于它关闭了 reader 参数)

UPDATE:更新:

Now that I see the update to your question, this boils down to accepting a reader parameter in a loop, and then wrapping it multiple times.现在我看到了对您的问题的更新,这归结为在循环中接受读取器参数,然后将其包装多次。 I suggest that you refactor your code so you wrap it with the PushbackReader only once.我建议你重构你的代码,这样你只用 PushbackReader 包装它一次。 Or move the initialization code of the reader into the inner method.或者将阅读器的初始化代码移动到内部方法中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM