If I invoke a BufferedReader the following way:
Integer.parseInt(new BufferedReader(new InputStreamReader(System.in)).readLine());
Will the JVM know to automatically close it when not in use? If not, how do I go about closing it?
If you are using java 7 or greater and your code is in try catch resource block, then it is Auto closes.
If in below versions you have to close with close(). For that you have to change your current way of using and get the reference.
Don't chain them, declare and assign variables, then close it after the usage.
InputStreamReader isReader;
BufferedReader bfReader;
try {
isReader = new InputStreamReader(System.in);
bfReader = new BufferedReader(isReader).readLine();
} catch (Exception e) {
// handle as per the requirement.
} finally {
bfReader.close();
}
If you use java 7, then, if you defined withing the try clause, then those will auto closable. Check here for more details
The try-with-resources statement is a try statement that declares one
or more resources. A resource is as 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. Any object that implements java.lang.AutoCloseable, which
includes all objects which implement java.io.Closeable, can be used as
a resource.
Related
I usually open files by fetching a BufferedReader:
Files.newBufferedReader(myPath).lines()
.doStuff()
.doMoreStuff();
What happens when the method throws an Exception, will the Reader be closed automatically like with a try-with-resource? I found no reference in the docs.
The Files.newBufferedReader is just a utility/factory method to create a BufferedReader for the File. Internally it eventually does a new BufferedReader() to create the BufferedReader.
So, you would have to treat it the same way as you would create the BufferedReader using the new operator. If you want it to be auto-closed at the end of the try block, you would have to use the try-with-resource as you would, if you had to create it using the new operator.
Will try-with-resources call flush() implicitly?
If it does, in the following code snippet, bw.flush() can be safely removed?
static void printToFile1(String text, File file) {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
bw.write(text);
bw.flush();
} catch (IOException ex) {
// handle ex
}
}
ps.
I don't see any description about it in official document:
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
https://docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html
Closeable and AutoCloseable are general-purpose interfaces that do not know anything about flushing. So you can't find any information about it in their documentation - except some words about releasing resources.
A Writer on the other hand is a more specific-purpose abstract class that now knows something about flushing. Some excerpt of the documentation for the method Writer.close():
Closes the stream, flushing it first.
So - yes - when using a writer, a close will always also flush. This basically means that you have to consult the documentation of the concrete classes that you are using when trying to find out what closing really does.
The resources are automatically closed when using try-with-resource block. As part of this process it will also invoke flush automatically.
As mentioned in doc for close method of BufferedWriter:
Closes the stream, flushing it first. Once the stream has been closed,
further write() or flush() invocations will cause an IOException to be
thrown.
Quoting javadoc of BufferedWriter.close():
Closes the stream, flushing it first.
The minimum amount of code to be written in this case:
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out))) {
bw.write("Test");
} catch (IOException e) {
// handle exception
}
Hence you don't need to call explicitly the flush method, as it will be called by the close method, as explained in the javadoc:
Closes the stream, flushing it first. Once the stream has been closed,
further write() or flush() invocations will cause an IOException to be
thrown. Closing a previously closed stream has no effect.
This behavior is inherited from the Writer class, hence besides BufferedWriter the same behavior is provided also by: CharArrayWriter, FilterWriter, OutputStreamWriter, PipedWriter, PrintWriter, StringWriter.
This behavior is not provided in the documentation of the tryWithResources or AutoCloseable as the behavior is specific to the given implementation of Writer. As Writerextends Closeable, it will call the close method when exiting the try {} block and the close method will first call
flush as already mentioned.
I really don't understand why other answers focus on the BufferedWriter not try-with-resources.
I, either, couldn't find any specification or mentions that the try-with-resources statements calls flush() on any objects of Flushable.
https://docs.oracle.com/javase/specs/jls/se13/html/jls-14.html#jls-14.20.3
Don't rely on any undocumented/unspecified behavior of vendor specific implementations.
try (OutputStream o = open()) {
//writeSome
o.flush(); // won't hurt!
}
From the Javdocs:
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. Any
object that implements java.lang.AutoCloseable, which includes all
objects which implement java.io.Closeable, can be used as a
resource.
The BufferedWriter.close() explicitly stated that:
Closes the stream, flushing it first. Once the stream has been closed, further write() or flush() invocations will cause an IOException to be thrown. Closing a previously closed stream has no effect.
I have this code:
Scanner fileReader = new Scanner(myFile);
// some code
fileReader = new Scanner(myFile);
// some more code
fileReader.close();
It does what I want it to (starts the reader again from the top of the file) but have I left a Scanner open by instantiating twice and only closing once? Should I have closed before I reinstantiated? What I have works, but I'd like to know whether it's good practice or not.
If I reinstantiate a Scanner, does the old one close?
Nope.
Should I have closed before I reinstantiated?
Yup.
What I have works, but I'd like to know whether it's good practice or not.
It is bad practice. It is a resource leak. If you do that too much, you are likely to find that new Scanner(myFile) will throw an exception, complaining that it has run out of file descriptors (or something like that).
The recommended practice is to use the try with resources syntax to ensure that the scanner gets closed no matter what. (Or if you are "old school" and / or stuck on Java 6 or earlier ... close the scanner in a finally block ... carefully.)
Example:
try (Scanner fileReader = new Scanner(myFile)) {
// some code
}
try (Scanner fileReader = new Scanner(anotherFile)) {
// some more code
}
It is not necessary to explicitly close either fileReader. Each try has an implicit finally block that calls close on all of the Closeable resources like the Scanner objects we created there.)
In Java 7, there is a try-with syntax that ensures objects like InputStream are closed in all code paths, regardless of exceptions. However, the variable declared in the try-with block ("is") is final.
try (InputStream is = new FileInputStream("1.txt")) {
// do some stuff with "is"
is.read();
// give "is" to another owner
someObject.setStream(is);
// release "is" from ownership: doesn't work because it is final
is = null;
}
Is there a concise syntax to express this in Java? Consider this exception-unsafe method. Adding the relevant try/catch/finally blocks would make the method much more verbose.
InputStream openTwoFiles(String first, String second)
{
InputStream is1 = new FileInputStream("1.txt");
// is1 is leaked on exception
InputStream is2 = new FileInputStream("2.txt");
// can't use try-with because it would close is1 and is2
InputStream dual = new DualInputStream(is1, is2);
return dual;
}
Obviously, I can have the caller open both files, placing them both in a try-with block. This is only one example of a case where I want to perform some operation on a resource before transferring ownership of it to another object.
The try-with is intended to be used in a situation where the identified resource must never persist outside the scope of the try block.
If you want to use the try-with construction, you must change your design as follows:
Delete the openTwoFiles() method. it is value free.
Create a constructor for the DualInputStream class that takes two file names and creates the two InputStreams. Declare that this constructor throws IOException and allow it to throw IOExceptions.
Use the new constructor in a try-with construct.
I expected to find XMLStreamReader to be AutoCloseable in Java 7. However, that is not the case. Is there a technical reason why StAX reader/writer interfaces were not (or should not be) retrofitted to implement AutoCloseable ? They already have close methods, whose intent is not different from the close method of AutoCloseable.
If you look closer to the close() method of AutoCloseable :
Closes this resource, relinquishing any underlying resources. This method is invoked automatically on objects managed by the try-with-resources statement.
Or even Closeable close() method :
Closes this stream and releases any system resources associated with it. If the stream is already closed then invoking this method has no effect.
Whereas the close() method of XMLStreamReader says :
Frees any resources associated with this Reader. This method does not close the underlying input source.
Indeed the input source is managed by the Reader which implement the Closeable interface. So it's the reader that can be close in the try-with-ressource.
For example :
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = null;
try (FileReader fr = new FileReader("file.xml")) { //Will close the FileReader
reader = factory.createXMLStreamReader(fr);
reader.close();
}
catch (XMLStreamException ex) {
if(reader!=null)try {
reader.close();
} catch (XMLStreamException ex1) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex1);
}
}
There is no technical reason why they couldn't have made these things AutoCloseable. I figure it just comes down to laziness or insufficient time looking for methods called close().