The variable fr only has scope within the try block. It is out of scope in the finally block. You need to declare it before the try block:

FileReader fr = null;
try {
    fr = new FileReader(file);
    BufferedReader br = new BufferedReader(fr);
    String line = null;
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    if (fr != null) {
        try {
            fr.close();
        } catch (IOException e) {
            // This is unrecoverable. Just report it and move on
            e.printStackTrace();
        }
    }
}

This is quite a common pattern of code, so it's good to remember it for future similar situations.

Consider throwing IOException from this method - printing track traces isn't very helpful to callers, and you wouldn't need the nested try catch around fr.close()

Answer from Bohemian on Stack Overflow
🌐
Oracle
docs.oracle.com › javase › tutorial › essential › exceptions › tryResourceClose.html
The try-with-resources Statement (The Java™ Tutorials > Essential Java Classes > Exceptions)
Because the FileReader and BufferedReader instances are declared in a try-with-resource statement, they will be closed regardless of whether the try statement completes normally or abruptly (as a result of the method BufferedReader.readLine throwing an IOException). Prior to Java SE 7, you can use a finally block to ensure that a resource is closed regardless of whether the try statement completes normally or abruptly.
🌐
GeeksforGeeks
geeksforgeeks.org › java › why-you-need-to-close-the-java-streams-in-finally-block
Why You Need to Close the Java Streams in Finally Block? - GeeksforGeeks
October 27, 2021 - // Java program to show the execution of the code // when exception is not caused import java.io.*; class GFG { public static void main(String[] args) { try { // open files System.out.println("Open files"); // do some processing int a = 45; int b = 5; int div = a / b; System.out.println("After dividing a and b ans is " + div); } catch (ArithmeticException ae) { System.out.println("exception caught"); // display exception details System.out.println(ae); } finally { System.out.println("Inside finally block"); // close the files irrespective of any exception System.out.println("Close files"); } } }
🌐
Tutorialspoint
tutorialspoint.com › java › io › fileoutputstream_close.htm
Java - FileOutputStream close() method
The close() method is called inside a finally block to ensure that the file is always closed, even if an exception occurs. Checking if (fos != null) prevents a NullPointerException in case the file wasn't successfully opened. The following example shows the usage of Java FileOutputStream close() ...
🌐
Blogger
javarevisited.blogspot.com › 2014 › 10 › right-way-to-close-inputstream-file-resource-in-java.html
Right way to Close InputStream and OutputStream in Java - Example
All resources opened in try block will automatically closed by Java, provided they implements Closable and AutoClosable. Since all InputStream and OutputStream are eligible to be used inside try-with-resource statements, you should take advantage of that. This is really great for Java programmer, as they are not as careful as their C++ counterparts, especially while releasing resource. Here is how does above code look like with try-with-resource statement. try (FileInputStream fis = new FileInputStream("../input/fxrates.txt"); FileOutputStream fos = new FileOutputStream("../output/fxrates.tx")) { // code for reading contents .....
🌐
Coderanch
coderanch.com › t › 238683 › certification › catch-finally-close-files
try-catch-finally ( when and how to close files ??) (OCPJP forum at Coderanch)
July 31, 2002 - hi folks - been studying from the book "Sun Certified Programmer for Java 2 Study Guide (Exam 310-025)", Second Edition, Copyright 2001 by The McGraw-Hill Companies. here's some code with accompanying review question found on page 210: the answer is that the program does not compile due to error on line 13 which is the line where we find "out.close()" in the finally section.
🌐
Coderanch
coderanch.com › t › 277812 › java › close-FileReader-finally-clause
close a FileReader in the finally clause (I/O and Streams forum at Coderanch)
The way the taught the same idiom in the course I took was to use a nested a try/ finally block for the business of opening and closing the streams and a try/ catch block for handling errors. Like so: Same result...
Find elsewhere
🌐
IIT Kanpur
iitk.ac.in › esc101 › 05Aug › tutorial › essential › exceptions › finally.html
The finally Block
finally { if (out != null) { System.out.println("Closing PrintWriter"); out.close(); } else { System.out.println("PrintWriter not open"); } } In the writeList example, you could provide for cleanup without the intervention of a finally block. For example, you could put the code to close the PrintWriter at the end of the try block and again within the exception handler for ArrayIndexOutOfBoundsException, as shown here: try { ... out.close(); // don't do this; it duplicates code } catch (FileNotFoundException e) { out.close(); // don't do this; it duplicates code System.err.println("Caught: FileNotFoundException: " + e.getMessage()); throw new RuntimeException(e); } catch (IOException e) { System.err.println("Caught IOException: " + e.getMessage()); } However, this duplicates code, thus making the code difficult to read and error prone if you later modify it.
🌐
DZone
dzone.com › coding › java › java 7: new feature – automatically close files and resources in try-catch-finally
Java 7: New Feature – Automatically Close Files and Resources in try-catch-finally
March 24, 2011 - } catch (FileNotFoundException ex) { System.err.println("Missing file " + file.getAbsolutePath()); } finally { if (is != null) { is.close(); } } With Java 7, you can create one or more “resources” in the try statement. A “resources” is something that implements the java.lang.AutoCloseable interface.
🌐
Javapractices
javapractices.com › topic › TopicAction.do
Java Practices->Finally and catch
BufferedReader reader = new BufferedReader(new FileReader(fileName)); try { //Any exception in the try block will cause the finally block to execute String line = null; while ((line = reader.readLine()) != null) { //process the line... } } finally { //The reader object will never be null here. //This finally is only entered after the try block is //entered. But, it's NOT POSSIBLE to enter the try block //with a null reader object. reader.close(); } } } Style 2
🌐
Program Creek
programcreek.com › 2013 › 12 › should-close-be-put-in-finally-block-or-not
Should .close() be put in finally block or not? – Program Creek
December 19, 2013 - //close() is in finally clause PrintWriter out = null; try { out = new PrintWriter( new BufferedWriter( new FileWriter("out.txt", true))); out.println("the text"); } catch (IOException e) { e.printStackTrace(); } finally { if (out != null) { out.close(); } }
🌐
Medium
medium.com › @nakulmitra2114 › finally-block-in-java-ac426ffb2d02
Finally Block in Java. This repository contains a detailed… | by Nakul Mitra | Medium
October 20, 2024 - If an exception occurs during file reading, the finally block ensures the BufferedReader is closed. This prevents resource leaks that could happen if resources are not released. Introduced in Java 7, the try-with-resources statement automatically ...
Top answer
1 of 2
3

The cleanest approach would be to do it using the try-with-resources statement as shown below:

private static void writetoFiles(String error) throws IOException {
    //...

    try (FileWriter updateerrorcode = new FileWriter("errorcode.txt")) {
        updateerrorcode.write(error);
    }

    //...
}

Do not catch an exception in a method if it can not handle it:

If the method, writetoFiles can not handle the exception, it should throw the same so that the calling method can handle it appropriately.

2 of 2
2

Use a try-with-resource statement:

private static void writetoFiles(String error) {
    try {
        File file = new File("errorcode.txt");
        if (!file.exists()) {
            file.createNewFile();
        } else {
            try (FileWriter updateerrorcode = new FileWriter("errorcode.txt")) {
                updateerrorcode.write(error);
            }
        }
    } catch (IOException e) {
        // TODO: Handle error condition
    }
}

To point out a separate issue...I think your logic is wrong in your example. If the output file doesn't exist, all your code does is create the file. Only if the file already exists does it write the error text to it. I expect that you want to write the text in either case. If this is true, you don't need the createNewFile call at all, as the FileWriter class will create the file if it doesn't already exist. So I think what you really want is this:

private static void writetoFiles(String error) {
    try (FileWriter updateerrorcode = new FileWriter("errorcode.txt")) {
        updateerrorcode.write(error);
    } catch (IOException e) {
        // TODO: Handle error condition
    }
}

This will cause the writer to be properly closed in both the normal execution case and the error throw case. I assume that in your actual code, you'll do something with that IOException when it is caught. I can't know what you want to do there, so I won't propose anything.

If you want to strictly use a finally block, you can do this instead:

FileWriter updateerrorcode = new FileWriter("errorcode.txt");
try {
    updateerrorcode.write(error);
}
catch (IOException e) {
    // TODO: Handle error condition
}
finally {
    updateerrorcode.close();
}

This is the only option you would have had in earlier versions of Java, prior to the addition of the try-with-resource construct. In this second method, you might want to catch an error from close(), but in all of my 25+ years of experience with Java, I don't recall a close() call on a file failing. I guess you'd get that if you were out of disk space on your target volume and so close() couldn't flush the stream's write buffer. This issue is a distinct advantage of the newer method...failure to close the file won't affect the throw/catch of an exception thrown by the write() call.

🌐
Baeldung
baeldung.com › home › java › java io › closing java io streams
Closing Java IO Streams | Baeldung
January 8, 2024 - This prevents other applications from writing or even accessing the file until the FileOutputStream is closed. Now let’s take a look at a few approaches for closing Java IO streams. These approaches help avoid the issues we discussed above and ensure proper resource management. This is the traditional way of closing IO streams. We close IO streams in the finally block.
Top answer
1 of 8
60

Note that the following is only applicable for Java 6 and earlier. For Java 7 and later, you should switch to using try-with-resources ... as described in other answers.

If you are trying to catch and report all exceptions at source (in Java 6 or earlier), a better solution is this:

ObjectOutputStream oos = null;
try {
   oos = new ObjectOutputStream(new FileOutputStream(file));
   oos.writeObject(shapes);
   oos.flush();
} catch (FileNotFoundException ex) {
    // complain to user
} catch (IOException ex) {
    // notify user
} finally {
    if (oos != null) {
        try {
            oos.close();
        } catch (IOException ex) {
            // ignore ... any significant errors should already have been
            // reported via an IOException from the final flush.
        }
    }
}

Notes:

  • The standard Java wrapper streams, readers and writers all propagate close and flush to their wrapped streams, etc. So you only need to close or flush the outermost wrapper.
  • The purpose of flushing explicitly at the end of the try block is so that the (real) handler for IOException gets to see any write failures1.
  • When you do a close or flush on an output stream, there is a "once in a blue moon" chance that an exception will be thrown due to disc errors or file system full. You should not squash this exception!.

If you often have to "close a possibly null stream ignoring IOExceptions", then you could write yourself a helper method like this:

public void closeQuietly(Closeable closeable) {
    if (closeable != null) {
        try {
            closeable.close();
        } catch (IOException ex) {
            // ignore
        }
    }
}

then you can replace the previous finally block with:

} finally {
    closeQuietly(oos);
}

Another answer points out that a closeQuietly method is already available in an Apache Commons library ... if you don't mind adding a dependency to your project for a 10 line method.

But be careful that you only use closeQuietly on streams where IO exceptions really are irrelevant.

UPDATE : closeQuietly is deprecated in version 2.6 of the Apache Commons API. Java 7+ try-with-resources makes it redundant.


On the issue of flush() versus close() that people were asking about in comments:

  • The standard "filter" and "buffered" output streams and writers have an API contract that states that close() causes all buffered output to be flushed. You should find that all other (standard) output classes that do output buffering will behave the same way. So, for a standard class it is redundant to call flush() immediately before close().

  • For custom and 3rd-party classes, you need to investigate (e.g. read the javadoc, look at the code), but any close() method that doesn't flush buffered data is arguably broken.

  • Finally, there is the issue of what flush() actually does. What the javadoc says is this (for OutputStream ...)

    If the intended destination of this stream is an abstraction provided by the underlying operating system, for example a file, then flushing the stream guarantees only that bytes previously written to the stream are passed to the operating system for writing; it does not guarantee that they are actually written to a physical device such as a disk drive.

    So ... if you hope / imagine that calling flush() guarantees that your data will persist, you are wrong! (If you need to do that kind of thing, look at the FileChannel.force method ...)

2 of 8
33

Current best practice for try/catch/finally involving objects that are closeable (e.g. Files) is to use Java 7's try-with-resource statement, e.g.:

try (FileReader reader = new FileReader("ex.txt")) {
    System.out.println((char)reader.read());
} catch (IOException ioe) {
    ioe.printStackTrace();
}

In this case, the FileReader is automatically closed at the end of the try statement, without the need to close it in an explicit finally block. There are a few examples here:

http://ppkwok.blogspot.com/2012/11/java-cafe-2-try-with-resources.html

The official Java description is at:

http://docs.oracle.com/javase/7/docs/technotes/guides/language/try-with-resources.html