Закрытие вложенного ридера
При чтении из текстового файла обычно создается 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
конструктор выдает исключение? Закрывает ли он вложенный ридер? Или это гарантированно не скинуть?
5 ответов
В общем-то, 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
}
Закрытие только BufferedReader
достаточно, потому что это оборачивает FileReader
, Если вы посмотрите на исходный код BufferedReader
вы увидите, что close
метод, закрывает завернутый поток.
Ничто не гарантировано, чтобы не бросать. Поскольку буфер выделен, он может выдать 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( );
}
И я согласен с вами, нет ничего более ценного, чем незаметно потерять обработчик файлов в долго работающем серверном приложении.
Если вы вызываете метод close BufferedReader, BufferedReader вызовет метод close FileReader. Таким образом, оба близких метода вызываются. Точнее, BufferedReader ничего не будет делать, НО вызывает метод close FileReader. Таким образом, это не имеет значения вообще. Хотя я думаю, что это хорошая практика, также вызывать метод close BufferedReader.