Java – Closing streams/sockets and try-catch-finally

character-encodingiojavasocketstry-catch

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:

  1. Why should I be closing the FileOutputStream in the finally section of the try-catch-finally? Surely I could just put the code sequentially after the try-catch?

  2. Why must I close the FileOutputStream separately rather than simply replacing new OutputStreamWriter(fos, ... with new 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?

  3. 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?

Best Solution

  1. 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.

  2. You don't have to. If you close a stream, any of its enclosed streams will be closed as well.

  3. 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.