Which means the InputStreamReader is never closed

Eh? In your code it is... And it will certainly handle the .close() of your resource stream as well. See below for more details...

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

You have another problem here: .getResourceAsStream() can return null; you may therefore have an NPE.

I'd do this 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 does extend AutoCloseable, yes; in fact it only differs, "signature wise", by the exception thrown (IOException vs Exception). But there is a fundamental difference in behavior.

From the javadoc of AutoCloseable's .close() (emphasis mine):

Note that unlike the close method of Closeable, this close method is not required to be idempotent. In other words, calling this close method more than once may have some visible side effect, unlike Closeable.close which is required to have no effect if called more than once. However, implementers of this interface are strongly encouraged to make their close methods idempotent.

And indeed, the javadoc of Closeable is clear about this:

Closes this stream and releases any system resources associated with it. If the stream is already closed then invoking this method has no effect.

You have two very important points:

  • by contract, a Closeable also takes care of all resources associated with it; so, if you close a BufferedReader which wraps a Reader which wraps an InputStream, all three are closed;
  • should you call .close() more than once, there is no further side effect.

This also means, of course, that you can choose the paranoid option and keep a reference to all Closeable resources and close them all; beware however if you have AutoCloseable resources into the mix which are not Closeable!

Answer from fge on Stack Overflow
Top answer
1 of 2
20

Which means the InputStreamReader is never closed

Eh? In your code it is... And it will certainly handle the .close() of your resource stream as well. See below for more details...

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

You have another problem here: .getResourceAsStream() can return null; you may therefore have an NPE.

I'd do this 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 does extend AutoCloseable, yes; in fact it only differs, "signature wise", by the exception thrown (IOException vs Exception). But there is a fundamental difference in behavior.

From the javadoc of AutoCloseable's .close() (emphasis mine):

Note that unlike the close method of Closeable, this close method is not required to be idempotent. In other words, calling this close method more than once may have some visible side effect, unlike Closeable.close which is required to have no effect if called more than once. However, implementers of this interface are strongly encouraged to make their close methods idempotent.

And indeed, the javadoc of Closeable is clear about this:

Closes this stream and releases any system resources associated with it. If the stream is already closed then invoking this method has no effect.

You have two very important points:

  • by contract, a Closeable also takes care of all resources associated with it; so, if you close a BufferedReader which wraps a Reader which wraps an InputStream, all three are closed;
  • should you call .close() more than once, there is no further side effect.

This also means, of course, that you can choose the paranoid option and keep a reference to all Closeable resources and close them all; beware however if you have AutoCloseable resources into the mix which are not Closeable!

2 of 2
6

But this seems worse. If InputStreamReader throws for some reason, the InputStream won't ever be closed, right?

That's right (although unlikely, the InputStreamReader constructor doesn't really do much).

The try-with-resources lets you declare as many resources as you'd like. Declare one for the wrapped resource, and another 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 would cause the InputStreamReader constructor to throw a NullPointerException. If you want to deal with that differently, adapt how you retrieve the resource that's meant to be wrapped.

The tutorial linked above presents 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 the explanation

In this example, the try-with-resources statement contains two declarations that are separated by a semicolon: ZipFile and BufferedWriter. When the block of code that directly follows it terminates, either normally or because of an exception, the close methods of the BufferedWriter and ZipFile objects are automatically called in this order. Note that the close methods of resources are called in the opposite order of their creation.

🌐
Waiting for Code
waitingforcode.com › home › java
Instruction try-with-resources on waitingforcode.com - Java blog posts
July 27, 2014 - The inspiration comes from other programming languages as Python and Ruby which already contained the solution for automatic resource management. Java's solution consists to put stream construction inside try block, as below: try (FileInputStream firstStream = new FileInputStream("/home/bartosz/myInputStream")) { // do something with defined InputStream } In this code, our FileInputStream will be closed automatically by Java.
🌐
GitHub
github.com › jaychenblue › scout-concordia › issues › 213
QD-7 Use try-with-resources or close this "InputStream" in a "finally" clause. · Issue #213 · jaychenblue/scout-concordia
April 1, 2020 - private void readTheFile(String fileName) throws IOException { Path path = Paths.get(fileName); try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) { reader.readLine(); // ... } // .. try (Stream<String> input = Files.lines("input.txt")) { input.forEach(System.out::println); } } private void doSomething() { OutputStream stream = null; try { stream = new FileOutputStream("myfile.txt"); for (String property : propertyList) { // ... } } catch (Exception e) { // ... } finally { stream.close(); } } Exceptions Instances of the following classes are ignored by this rule because close has no effect: java.io.ByteArrayOutputStream java.io.ByteArrayInputStream java.io.CharArrayReader java.io.CharArrayWriter java.io.StringReader java.io.StringWriter Java 7 introduced the try-with-resources statement, which implicitly closes Closeables.
Author   JenYn
🌐
Jenkov
jenkov.com › tutorials › java-exception-handling › try-with-resources.html
Java Try With Resources
August 25, 2019 - The Java try with resources construct, AKA Java try-with-resources, is an exception handling mechanism that can automatically close resources like a Java InputStream or a JDBC Connection when you are done with them.
🌐
Oracle
docs.oracle.com › javase › tutorial › essential › exceptions › tryResourceClose.html
The try-with-resources Statement (The Java™ Tutorials > Essential Java Classes > Exceptions)
The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement.
🌐
Veracode
veracode.com › blog › managing-appsec › exception-handling-try-resources-statement-java-7
Exception Handling with Try with Resources Statement in Java 7 | Veracode
September 6, 2015 - In this article, we will have a look at how try-with-resources can avoid nested blocks and help correctly close multiple resources. Consider the following snippet of code. We are trying to copy the contents of the input file into the output file using I/O streams. public void copy() throws FileNotFoundException { InputStream input = new FileInputStream("in.txt"); OutputStream output = new FileOutputStream("out.txt"); byte[] buffer = new byte[1024]; try { try { while (-1 != input.read(buffer)) { output.write(buffer); } } catch (IOException ex) { Logger.getLogger(Easy.class.getName()).log(Level.SEVERE, null, ex); } finally { input.close(); output.close(); } } catch (IOException ex) { Logger.getLogger(Easy.class.getName()).log(Level.SEVERE, null, ex); } }
🌐
Baeldung
baeldung.com › home › java › core java › java – try with resources
Java - Try with Resources | Baeldung
May 11, 2024 - The resources declared need to implement the AutoCloseable interface. Find out if it is a bad practice to catch Throwable. ... The simple and obvious way to use the new try-with-resources functionality is to replace the traditional and verbose try-catch-finally block.
🌐
Medium
medium.com › @reetesh043 › using-try-with-resources-in-java-simplifying-resource-management-bd9ed8cc8754
Try-With-Resources In Java: Simplifying Resource Management | by Reetesh Kumar | Medium
January 10, 2024 - In these examples, the InputStream and OutputStream objects are both automatically closed when the try block exits, regardless of whether an exception is thrown. This ensures that resources are always properly released, even in the event of an error. // Connect to the database try (Connection connection = DriverManager.getConnection(url, username, password)) { // Prepare a statement try (PreparedStatement statement = connection.prepareStatement("SELECT * FROM users")) { // Execute the statement try (ResultSet resultSet = statement.executeQuery()) { // Iterate over the results while (resultSet.next()) { String username = resultSet.getString("username"); String pass = resultSet.getInt("password"); // Do something with the data } } } }
🌐
Orkhan Huseynli
orkhan-huseyn.github.io › 2020 › 03 › 26 › javas-try-with-resources
Java's try with resources
November 5, 2022 - If returned values is less than 0 (zero) then the stream is ended. Since the InputStream is for reading binary data, we also cast the integer value to byte. Now, the above code is somehow complete, but ignores an important point: the stream is not closed after reading from it. We can close it in try-catch’s finally block.
Find elsewhere
🌐
Medium
medium.com › thefreshwrites › how-to-use-try-with-resource-in-java-9c0b4ae48d21
How To Use Try With Resource In Java | Exception Handing | by Mouad Oumous | The Fresh Writes | Medium
February 17, 2024 - The Java try with resources construct, AKA Java try-with-resources, is an exception handling mechanism that can automatically close resources like a Java InputStream or a JDBC Connection when you are done with them.
🌐
Baptiste-wicht
baptiste-wicht.com › posts › 2010 › 08 › java-7-try-with-resources-statement.html
Java 7 : The new try-with-resources statement | Blog blog("Baptiste Wicht");
August 24, 2010 - So let's use try-with-resources statement to simplify this code, who becomes : private static void customBufferStreamCopy(File source, File target) { try (InputStream fis = new FileInputStream(source); OutputStream fos = new FileOutputStream(target)){ byte[] buf = new byte[8192]; int i; while ((i = fis.read(buf)) != -1) { fos.write(buf, 0, i); } } catch (Exception e) { e.printStackTrace(); } }
🌐
Javatpoint
javatpoint.com › java-try-with-resources
Java Try with Resources - javatpoint
Java Try with Resources with examples and topics on functional interface, anonymous class, lambda for list, lambda for comparable, default methods, method reference, java date and time, java nashorn, java optional, stream, filter etc.
🌐
Java Guides
javaguides.net › 2018 › 08 › the-try-with-resources-statement-with-examples.html
Java try-with-resources Statement
June 21, 2024 - This feature helps in writing cleaner and more reliable code by ensuring that resources are closed properly, avoiding resource leaks. ... The try-with-resources statement is a try statement that declares one or more resources. A resource is ...
🌐
Blogger
javarevisited.blogspot.com › 2014 › 10 › right-way-to-close-inputstream-file-resource-in-java.html
Right way to Close InputStream and OutputStream in Java - Example
} catch (IOException ioex) { System.out.println("Failed to copy files : " + ioex.getMessage()); ioex.printStackTrace(); } As you can see, we have got rid of lot of boiler plate try-finally code. Since you can declare more than one resource inside try-with-resource block, allocate your streams, channels, and readers there. That's all on this post about right way of closing InputStream and OutputStream in Java.
🌐
Kotlin Discussions
discuss.kotlinlang.org › language design
Concise way to manage resource with exception in kotlin - Language Design - Kotlin Discussions
December 1, 2017 - When doing IO operation, IOException ... to make a method never throw IOException and resource will properly closed when the method return. Simplified example in Java public ParseResult parse(File file) { try (InputStream stream = new FileInputStream(file)) ......