Try-with-resources, where can I stream around a stream using InputStreamReader?

I can overestimate this, but I just wrote the code:

try (InputStream in = ModelCodeGenerator.class.getClassLoader().getResourceAsStream("/model.java.txt")) { modelTemplate = new SimpleTemplate(CharStreams.toString(new InputStreamReader(in, "ascii"))); } 

This means that the InputStreamReader never closes (but in this case, we know that its close method simply closes the underlying InputStream.)

You can write this as:

 try (InputStreamReader reader = new InputStreamReader(...)) 

But it seems worse. If InputStreamReader throws for some reason, InputStream will never be closed, right? This is a common problem in C ++ with constructors that other constructors call. Exceptions can cause a memory / resource leak.

Is there any best practice here?

+5
source share
2 answers

This means that InputStreamReader never closes.

A? In your code, this is ... And that will certainly handle the .close () of your resource stream. See below for more details.

As @SotiriosDelimanolis mentions , however, you can declare more than one resource in the "resource block" of the try-with-resources statement.

You have one more problem: .getResourceAsStream() may return null; therefore you may have NPE.

I would do it if I were you:

 final URL url = ModelCodeGenerator.class.getClassLoader() .getResource("/model.java.txt"); if (url == null) throw new IOException("resource not found"); try ( final InputStream in = url.openStream(); final Reader reader = new InputStreamReader(in, someCharsetOrDecoder); ) { // manipulate resources } 

There is a very important point to consider , however ...

Closeable extends AutoCloseable , yes; in fact, it differs only in “signature wise”, with the exception of the abandoned ones ( IOException vs Exception ). But there is a fundamental difference in behavior.

From javadoc AutoCloseable .close() (my attention):

Note: unlike the Closeable Closeable method, this closure method is not required idempotent. In other words, calling this close method several times may have some visible side effect, unlike Closeable.close, which should not have an effect when called more than once . However, developers of this interface are strongly encouraged to use their close methods idempotent.

And indeed, javadoc Closeable makes this clear:

Closes this thread and frees the associated system resources. If the thread is already closed, calling this method has no effect.

You have two very important points:

  • By contract, a Closeable also takes care of all resources associated with it; therefore, if you close the BufferedReader , which wraps the Reader , which wraps the InputStream , all three close;
  • If you call .close() more than once, there will be no additional effect.

It also means, of course, that you can select the paranoid parameter and keep the link to all Closeable resources and close all of them; but if you have AutoCloseable resources in the mix that are not Closeable !

+11
source

But it seems worse. If for some reason InputStreamReader selected, InputStream will never be closed, right?

That's right (although it is unlikely that the InputStreamReader constructor is actually not very much).

try-with-resources allows you to declare as many resources as you want. Declare one for the wrapped resource and the other for the InputStreamReader .

 try (InputStream in = ModelCodeGenerator.class .getClassLoader() .getResourceAsStream("/model.java.txt"); InputStreamReader reader = new InputStreamReader(in)) {...} 

Note that getResourceAsStream can potentially return null , which will cause the InputStreamReader constructor to throw a NullPointerException . If you want to deal with it differently, adapt the way you get the resource to be wrapped.

The tutorial above provides this example.

 try ( java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName); java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset) ) { 

with an explanation

In this example, the try-with-resources statement contains two declarations separated by semicolons: ZipFile and BufferedWriter . When the block of code that immediately follows it ends, either as usual or because of an exception, closing the methods of the BufferedWriter and ZipFile automatically called in that order. Note that tight resource methods are called in the opposite order of their creation.

+4
source

Source: https://habr.com/ru/post/1211646/


All Articles