Закрыть файл в блоке finally не работает

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

fr.close() показывает ошибку:

фр не может быть решен

Я читал, что закрытие файла в блоке finally является хорошей практикой.
Что я делаю не так?


person noMAD    schedule 24.01.2012    source источник


Ответы (3)


Переменная fr имеет область действия только в пределах блока try. Это выходит за рамки блока finally. Вам нужно объявить его перед блоком try:

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

Это довольно распространенный шаблон кода, поэтому хорошо запомнить его для будущих подобных ситуаций.

Рассмотрите возможность выбрасывания IOException из этого метода — печать трассировки не очень полезна для вызывающих, и вам не понадобится вложенный try catch вокруг fr.close()

person Bohemian♦    schedule 24.01.2012
comment
Если я это сделаю, мне будет сказано, что мне нужно добавить еще один блок Try при закрытии файла. Я читал предыдущий пост, где было сказано, что с этим ничего нельзя поделать. Итак, это был бы лучший способ, не так ли? - person noMAD; 24.01.2012
comment
Да, это раздражает. Для этого часто пишут служебный метод с именем closeQuietly (или аналогичный). Он ловит и игнорирует исключение. - person user949300; 24.01.2012
comment
См. отредактированный ответ для вложенного try/catch - также распространенный шаблон - person Bohemian♦; 24.01.2012
comment
Есть ли причина не делать FileReader fr = new FileReader(file); снаружи? Это устранило бы необходимость проверять fr != null, не так ли? Сложность заключается в том, что catch (FileNotFoundException e) необходимо переместить во внешнюю попытку: /a> но мне это все равно кажется чище. Но, возможно, это просто мои привычки Python. - person Beni Cherniavsky-Paskin; 08.03.2015

Теперь блок finally не нужен,

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

    String line = null;

    }

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

теперь автоматически закройте ваши читалки

person Kushan    schedule 24.01.2012
comment
Да, но только в Java 7. В Java 6 и более ранних версиях этого нет. - person user949300; 24.01.2012
comment
Если кто-то задается вопросом, почему это так, найдите try с ресурсами - person axxis; 06.02.2016
comment
дополнительная информация: оператор try-with-resources гарантирует, что каждый ресурс закрывается в конце инструкции. - person hd84335; 11.03.2019

У вас проблема с прицелом. Если вы действительно хотите использовать этот синтаксис, вы должны исправить его следующим образом:

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

таким образом, fr будет существовать в области действия блока finally.

person marimaf    schedule 24.01.2012