What is the correct way to open a stream in Java
I will be giving a Java lecture to physics students and I would like to know how to open the file correctly.
In many of my professional applications, I have done something like this:
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("file")));
try{
....
}finally {
bufferedWriter.close();
}
which is IMHO OK, meaning the reader will be closed.
When I was putting this in an example for my students, I was wondering what would happen if the constructor InputStreamReader
throws an exception --- FileInputStream will be open, but my code will not be closed (since these objects are created outside the try-finally block.
So this is the correct idiom, and if so, why? If this is the wrong idiom to open a stream, please point me to the correct one!
Edit . I am looking for an idiom that is correct and very easy to write and understand, physics students are new to programming.
Edit . It's stupid to me. I copied the wrong example. If I use Writers instead of readers, it gets more complicated.
source to share
Reading with input streams
Before Java 7 this is how you can do it
InputStream in = null;
try {
in = new FileInputStream("simple.csv");
BufferedReader buf = new BufferedReader(new InputStreamReader(in));
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {}
}
}
For Java 7, you can use Closeable
something like
try (BufferedReader buf = new BufferedReader(...)) {}
EDIT: Why didn't I close the buf
above? Look at the source codeBufferedReader.close()
public void close() throws IOException {
synchronized (lock) {
if (in == null)
return;
in.close();
in = null;
cb = null;
}
}
Recording with output streams
EDIT 2: The same principle applies to writers. However, if you are really interested in the flow of the thread when happens IOException
, then you should check both writer
and stream
for null
and try closing them accordingly. This does provide a lot of additional code, though. It might look something like this:
BufferedWriter buf = null;
OutputStream out = null;
try {
out = new FileOutputStream("file");
buf = new BufferedWriter(new OutputStreamWriter(out));
} finally {
if (buf != null) {
try { buf.close(); } catch (IOException ex){}
}
if (out != null) {
try { out.close(); } catch (IOException ex){}
}
}
It's not pretty. You can introduce a helper procedure to close your streams or search in Java 7, orApache IOUtils
source to share
In this special case (nested constructors) FileInputStream
will remain open. You will need to do it like this (if you really need to make sure the stream is closed):
final FileInputStream fis = new FileInputStream("");
try
{
final BufferedReader br = new BufferedReader(new InputStreamReader(fis));
// ...
}
finally
{
fis.close();
}
The closure FileInputStream
should be sufficient.
Edit: The same logic can apply to writers. If the open FileOutputStream
fails, it throws an exception that prevents the try / finally block from being executed. And if any other write constructor fails, the output stream is still closed with a clause final
.
source to share