Here is an example I have questions about (it comes from another SO question):
public static void writeToFile (final String filename)
{
PrintWriter out = null;
FileOutputStream fos = null;
try
{
fos = new FileOutputStream(filename);
out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(fos, "UTF-8")));
for (final String line : log)
{
out.println(line);
}
out.flush();
out.close();
}
catch (final Exception e)
{
System.err.println("Unable to write log to file.");
}
finally
{
if (fos != null)
{
try
{
fos.close();
}
catch (final IOException e)
{
System.err.println("Unable to write log to file.");
}
}
}
}
Now I think this code works fine and releases all the resources where it should etc. My questions are:
Why should I be closing the
FileOutputStream
in thefinally
section of thetry-catch-finally
? Surely I could just put the code sequentially after thetry-catch
?Why must I close the
FileOutputStream
separately rather than simply replacingnew OutputStreamWriter(fos, ...
withnew OutputStreamWriter(new FileOutputStream(filename), ...
? If I close the FileOutputStream first, will that automatically close the rest and release the resources? Same questions apply for sockets, if I close a socket connection does that automatically close the stream readers/writers and release the resources?I've been told repeatedly to ensure that I read and write streams with "UTF-8" due to different systems having different charsets (or something along those lines). Is this still applicable when reading/writing RAW byte data (say from a non-text file, or the result of an encryption) as I thought charsets where to do with textual characters only?
why should I be closing the FileOutputStream in the finally section of the try-catch-finally?
You can put the
close()
at the end of all the writing/reading operations block, but if something goes wrong while in there(reading/writing), you'll reach the exception handling block and no stream will be closed. If you choose to put theclose()
in the exception handling block and everything goes fine, guess what?... no stream will be closed. So you can do it in both blocks of code, but that way the code will be less readable. So putting it on the finally block assures you that either way it will be closed.Second, you should close only the last stream that has been chained. so if you have this.
You only need to
That will close the other streams associated to the out stream.
The UTF-8 part depends on the type of data encoding you're trying to read, if you encode UTF-8, decode UTF-8.
Because if your code throw an un-handled exception, the snippet after the try-catch bloc will never gets executed. This is the case with
NullPointerExcpetion
, for example.You don't have to. If you close a stream, any of its enclosed streams will be closed as well.
No. This is the case only when converting bytes to characters (or the other way around). You're specifying the charset to the
OutputStreamWriter
, which is responsible for converting characters to bytes.On the first point - if your code threw an error, rather than an exception the FileOutputStream would not be closed if the close statement was not in the finally. It's a little artificial in your case as you are catching Exception, but in a more typical situation where a more specific exception would be caught, unless you tidy up the resources in the the finally block, execution of the method may terminate before it reaches the code that will close the resources.