Как решить проблему с закрытием FileStream

Я закрыл файл steam в try/finally, но анализ кода предупреждает меня:

  • Возможная ошибка при закрытии FileOutputStream
  • Возможная ошибка при закрытии PrintWriter
  • Возможная ошибка при закрытии OutputStreamWriter

Как может случиться провал? Как я могу убедиться, что FileStream закрыт?

public void writeFile(String filepath)
{
    BufferedWriter bw = null;
    PrintWriter pw = null;
    try {
        File file = new File(filepath);
        bfw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
        pw = new PrintWriter(bfw);

     //do something

    }catch(Exception e){
        e.printStackTrace();
    }
    finally{
        try{
            bfw.close();
            pw.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

person tensor    schedule 29.03.2018    source источник


Ответы (3)


Как может случиться провал?

Смотрите свой блок finally:

finally{
    try{
        bfw.close();   <== exception occured here
        pw.close();    <== this is not execute
    }catch(Exception e){
        e.printStackTrace();
    }
}

Что делать, если в bfw.close() возникает исключение? pw.close() никогда не будет выполняться. А это приводит к утечке ресурсов.

Как я могу убедиться, что FileStream закрыт?

Кто-то уже указал на использование try/catch/finally внутри finally. Но если вам не нравится, что так много попыток поймать наконец, я бы посоветовал вам использовать библиотеку, например Коммоны ввода/вывода Apache.

Решение:

try {

   ........
} finally {
    IOUtils.closeQuietly(bfw);
    IOUtils.closeQuietly(pw);
}

И да, у вас всегда есть try-with-resources, если с использованием Java 7 или выше.

person VeKe    schedule 29.03.2018
comment
Я думаю, что ответом является сочетание Am_I_Helpful и VedX. Хорошо сделать нулевую проверку перед close() и перехватить каждое исключение, происходящее в close() в случае утечки ресурсов. VedX - хороший ответ с четким объяснением, но он не может обрабатывать исключения. Поэтому я выбираю это как ответ - person tensor; 29.03.2018
comment
Вы в курсе, что IOUtils из commons-io имеет открытые уязвимости в системе безопасности, @tensor ? - person N00b Pr0grammer; 31.03.2018

Если вы используете Java-7 и выше, вы можете использовать try with resources

File file = new File(filepath);
try(BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
    PrintWriter pw = new PrintWriter(bfw);)
{
    ...
}
catch(Exception exception) //This is optional
{
    exception.printStackTrace();
}

Вы можете использовать блоки catch и finally с оператором try-with-resources точно так же, как с обычным оператором try.

Надеюсь это поможет!

person N00b Pr0grammer    schedule 29.03.2018
comment
И вы можете вообще не использовать блоки catch и finally, потому что неявный блок finally уже присутствует. - person daniu; 29.03.2018

Если при закрытии bw произойдет исключение, вы не закроете pw. Попробуй это:

finally{
    try{
        bw.close();
    } catch(Exception e){
        e.printStackTrace();
    } finally {
        pw.close();
    }
}
person Evgeniy Dorofeev    schedule 29.03.2018
comment
на самом деле pw.close() внутренне закрывает базовый поток - bw. Лучшее решение (кроме java 7): pw = new PrintWriter (новый BufferedWriter (новый OutputStreamWriter (новый FileOutputStream (файл), UTF-8))); - person Evgeniy Dorofeev; 29.03.2018