Подтвердить что ты не робот

Закрытие вложенного чтения

При чтении из текстового файла обычно создается FileReader, а затем гнездится в BufferedReader. Кого из двух читателей я должен закрыть, когда я закончил читать? Это имеет значение?

FileReader fr = null;
BufferedReader br = null;
try
{
    fr = new FileReader(fileName);
    br = new BufferedReader(fr);
    // ...
}
finally
{
    // should I close fr or br here?
}

Я немного параноик, когда речь заходит об исключении-безопасности. Что происходит, когда конструктор BufferedReader создает исключение? Закрывает ли он вложенный читатель? Или он не может бросить?

4b9b3361

Ответ 1

Как правило, close() на внешней оболочке потока вызывает close() на обернутых потоках. Однако, если вы считаете, что конструктор будет генерировать исключение, используйте либеральный интерфейс Closeable.

FileReader fr = new FileReader(fileName);
Closeable res = fr;
try {
    BufferedReader br = new BufferedReader(fr);
    res = br;
} finally {
    res.close();
}

Итак, даже если JVM закончила пустое место для буфера и выбросила ошибку, вы не пропустили бы дескриптор файла.

Для Java 7 и выше используйте try-with-resources:

try (FileReader fr = new FileReader(fileName);
    BufferedReader br = new BufferedReader(fr)) {
  // do work
}

Ответ 2

Закрытие только BufferedReader достаточно, потому что оно обертывает FileReader. Если вы посмотрите исходный код BufferedReader, вы увидите, что метод close закрывает обернутый поток.

Ответ 3

Закройте BufferedReader в блоке finally.

Ответ 4

Если вы вызовете метод закрытия BufferedReader, BufferedReader вызовет метод закрытия FileReader. Таким образом, вызываются оба метода. Точнее BufferedReader ничего не сделает, но вызовет метод закрытия FileReader. Таким образом, это не имеет значения. Хотя я считаю, что хорошая практика также вызывает метод закрытия BufferedReader.

Ответ 5

Ничто не гарантирует, что он не бросит. Поскольку буфер выделен, он может вызывать OutOfMemoryError. Обычно я разделяю свой код на 2 раздела: приобретаю ресурсы, а затем использую ресурсы. Каждый раздел обычно имеет уникальные потребности в очистке

Вот код для иллюстрации:

// Acquire resources section.

final FileReader fr = new FileReader( fileName );

BufferedReader br = null;

try
{
    br = new BufferedReader(fr);
}
finally
{
    if ( br == null )
    {
        // Note that you are closing the fr here
        fr.close( );
    }
}

// Use resources section
try
{
    // ... use br
}
finally
{
    // Now that br is safely constructed, just all its close
    br.close( );
}

И я согласен с тобой, нет ничего, что бы стоило, чем просто потерять обработчик файлов в длинном серверном приложении.