16
try {
    FileReader fr = new FileReader(file);
    BufferedReader br = new BufferedReader(fr);
    String line = null;
} catch (FileNotFoundException fnf) {
    fnf.printStackTrace();
} finally {
    fr.close();
}

The fr.close() shows an error:

fr cannot be resolved

I had read that closing a file in the finally block is a good practice.
What is that am doing wrong?

Bohemian
  • 412,405
  • 93
  • 575
  • 722
noMAD
  • 7,744
  • 19
  • 56
  • 94

4 Answers4

29

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()

Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • If I do that then it says I need to add another Try block while closing the file. I read a previous post where it was said that nothing can be done about that. So, this would be the best way is it? – noMAD Jan 24 '12 at 03:19
  • Yes, that is annoying. One often writes a utility method, named "closeQuietly" (or similar) to do this. It catches and ignores the Exception. – user949300 Jan 24 '12 at 03:23
  • See edited answer for nested `try/catch` - also a common pattern – Bohemian Jan 24 '12 at 03:24
  • Is there a reason not to do the `FileReader fr = new FileReader(file);` outside? This would eliminate the need to check `fr != null`, no? A complication is that `catch (FileNotFoundException e)` has to be moved to an outer try: https://gist.github.com/cben/6e092536e8f2072ab83f but that still reads cleaner to me. But maybe that's just my [Python habits](http://stackoverflow.com/a/3770375/239657). – Beni Cherniavsky-Paskin Mar 08 '15 at 12:25
10

Now finally block is not needed,

try (FileReader fr = new FileReader(file);
    BufferedReader br = new BufferedReader(fr);){

    String line = null;

    }

} catch(FileNotFoundException fnf) {
    fnf.printStackTrace();
} 

now automatically close your readers

Kushan
  • 10,657
  • 4
  • 37
  • 41
  • 2
    Yes, but only in Java 7. Java 6 and earlier do not have this. – user949300 Jan 24 '12 at 03:25
  • 1
    In case anyone wonders why is this, search for "try with resources" – axxis Feb 06 '16 at 13:06
  • 1
    more info: [try-with-resources](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) statement ensures that each resource is closed at the end of the statement. – hd84335 Mar 11 '19 at 16:48
0
public static void main(String[] args) throws IOException{
        FileReader file1 = null;
        try{
            file1 = new FileReader("blaaa.txt");//this file does not exist
        }
        catch (FileNotFoundException e){}
        catch (IOException e)  {e.printStackTrace();}
        finally {
            try{file1.close();}
            catch (NullPointerException e){
            }
            finally {
                System.out.println("Thank you, please try again");
            }
        }
    }
0

You have a problem with your scopes. If you really want to use that syntax you should fix it like this:

FileReader fr = null;
try {
    fr = new FileReader(file);
    BufferedReader br = new BufferedReader(fr);
    String line = null;
} catch (FileNotFoundException fnf) {
    fnf.printStackTrace();
} finally {
    if( fr != null)
       fr.close();
}

that way, fr will exist in the finally's block scope.

marimaf
  • 5,382
  • 3
  • 50
  • 68