Question

I was just looking back over some code we wrote in a java class that I'm taking. I noticed that in the finally block there is a try/catch for closing the reader, but not the writer. I'll copy the code below. Can anyone explain why that would be? I'd like to understand better.

public class UsingFiles {
public static void main(String[] args) {
    // open the input stream (from the file of this program)
    BufferedReader reader = null;
    PrintWriter writer = null;
    try {
        reader = new BufferedReader(new FileReader("./src/UsingFiles.java"));
        writer = new PrintWriter("reverseFile.txt");
        // String line;
        // while ((line = reader.readLine()) != null) {
        // System.out.println(line);
        // }
        // print the file in reverse order
        // use recursion
        reverseFile(reader, writer);
    } catch (FileNotFoundException e) {
        System.out.println("Couldn't open the file!");
    } catch (IOException e) {
        System.out.println("Problem reading the file");
    } finally {
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                System.out.println("Couldn't close the reader");
            }
        }
        if (writer != null) {
            writer.close();
        }
    }
}

private static void reverseFile(BufferedReader reader, PrintWriter writer)
        throws IOException {
    String line = reader.readLine();
    if (line != null) {
        reverseFile(reader, writer);
        writer.println(line);
    }
}
Était-ce utile?

La solution

There are two possibilities that I can think of:

  1. It's an oversight
  2. Both calls to close() can throw an exception. If the first one throws an exception, the second one would be skipped - unless of course the first one was wrapped in its own try/catch block. The second one doesn't need a try/catch block since if it fails, there is no subsequent code that will be skipped

In the "real world", I would say that the answer is #1. The reason I would think #2 to be unlikely is that there is usually some other code that you will want to execute, even if you can't close some stream. This would be especially true had the catch blocks not caught an exception (or re-threw a different exception) since a fresh exception in the finally block would replace the original exception and you would never know that it had happened.

Update

As another answer has pointed out, PrintWriter.close() does not in fact throw an IOException, even though the parent interface Writer does declare that close() can throw an IOException. So that may be a better explanation.

Autres conseils

I believe the intent was to attempt to close the writer even if the reader failed to close. If closing the reader throws an IOException, you will never execute the rest of the finally block.

This is because PrintWriter never throws exception during close(). See API. This

            try {
                writer.close();
            } catch(IOException e) {
                System.out.println("Couldn't close the writer");
            }

will result in compiler error: Unreachable catch block for IOException. This exception is never thrown from the try statement body

It actually SHOULD be closed.

http://docs.oracle.com/javase/7/docs/api/java/io/PrintWriter.html

Anytime you use a resource on the system, it's great practice to close a the objects that have access to it.

There is no need to close reader in try block of finally block if you are using try with resource

try(reader = new BufferedReader(new FileReader("./src/UsingFiles.java"))
{

}

catch(Exception e)
{
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top