Preciso fechar () o FileReader e o BufferedReader?

188

Estou lendo um arquivo local usando um BufferedReader envolvido em um FileReader:

BufferedReader reader = new BufferedReader(new FileReader(fileName));
// read the file
// (error handling snipped)
reader.close();

Eu preciso close()do FileReaderbem, ou será que a alça de invólucro que? Eu vi código em que as pessoas fazem algo assim:

FileReader fReader = new FileReader(fileName);
BufferedReader bReader = new BufferedReader(fReader);
// read the file
// (error handling snipped)
bReader.close();
fReader.close();

Esse método é chamado de um servlet e eu gostaria de ter certeza de não deixar nenhum identificador aberto.

Zilk
fonte
4
Sabe, você pode simplesmente ler a fonte para obter informações como essa. Está tudo lá no src.zip no diretório de instalação do JDK, ou você pode lê-lo on-line em, por exemplo, docjar.com/html/api/java/io/BufferedReader.java.html
gustafc
50
Dizer a alguém para ler a fonte é pior do que dizer "RTFM!". E se a fonte tiver um bug; implicitamente, queremos saber qual é o comportamento correto ?
Raedwald 5/07
1
Bem ... deste ponto de vista: apontar para especificações da API não é melhor então. Se a fonte não tiver um bug que faça com que não se comporte como especificado nos documentos, você não poderá confiar nos documentos. Portanto, não há uma boa maneira de responder a essa pergunta.
Atmocreations
@Atmocreations A próxima versão de manutenção pode alegremente corrigir um bug em que você confia se apenas olhar a fonte. Você realmente precisa saber qual é o comportamento documentado. Nada de errado em olhar para a fonte, é claro, mas você não pode assumir que a fonte não mudará. Mudar o comportamento documentado é geralmente muito maior do que consertar um bug.
James Moore

Respostas:

202

não.

BufferedReader.close()

fecha o fluxo de acordo com o javadoc para BufferedReader e InputStreamReader

assim como

FileReader.close()

faz.

Atmocreations
fonte
12
A menos que o construtor BufferedReaderlance uma exceção. É mais fácil fechar o fluxo subjacente, embora você precise se preocupar com decoradores com outros recursos e buffer.
Tom Hawtin # tackline
9
O Javadoc não diz se BufferedReader.close()fecha o leitor subjacente. Sua descrição é simplesmente copiada Reader.close(). Este pode ser o comportamento real na prática, mas não está documentado.
John Kugelman
3
Se o comportamento real fosse diferente, deveria ter sido documentado como tal. Caso contrário, a documentação é inútil. O programador deve poder considerar a documentação completa e específica.
Atmocreations
6
Não importa se a documentação real deveria ter sido alterada ou não, Reader#close()os javadocs não dizem se a fecha ou não, está envolto no Reader ou não. Tudo o que diz relacionado a isso é Closes the stream and releases any system resources associated with it.que não é explícito o suficiente para dizer que fecha ou não o recurso. 'Liberar o recurso' pode também estar removendo qualquer referência ao recurso no BufferedReader ... o que significa que o recurso não está fechado.
searchengine27
99

Como outros já apontaram, você só precisa fechar o invólucro externo.

BufferedReader reader = new BufferedReader(new FileReader(fileName));

Há uma chance muito pequena de que isso possa vazar um identificador de arquivo se o BufferedReaderconstrutor lançar uma exceção (por exemplo,OutOfMemoryError ). Se seu aplicativo estiver nesse estado, o quão cuidadosa sua limpeza deve ser depende de quão crítico é que você não priva o sistema operacional dos recursos que ele deseja alocar para outros programas.

O Closeable interface pode ser usada se um construtor de wrapper provavelmente falhar no Java 5 ou 6:

Reader reader = new FileReader(fileName);
Closeable resource = reader;
try {
  BufferedReader buffered = new BufferedReader(reader);
  resource = buffered;
  // TODO: input
} finally {
  resource.close();
}

O código Java 7 deve usar o padrão try-with-resources :

try (Reader reader = new FileReader(fileName);
    BufferedReader buffered = new BufferedReader(reader)) {
  // TODO: input
}
McDowell
fonte
1
"O código Java 7 deve usar o padrão try-with-resources". Obrigado, é exatamente o que eu estava procurando. Essa solução foi escrita em 09, portanto o paradigma da tentativa com recursos provavelmente deve ser a nova recomendação. Além disso, oferece uma resposta melhor ao OP em relação à resposta aceita e com maior votação.
tresf 10/02
5

De acordo com a fonte BufferedReader, nesse caso, bReader.close chame fReader.close para que tecnicamente você não precise chamar o último.

Csaba_H
fonte
Dado que há documentação explicando como ela deve ser usada, você deve examinar a documentação primeiro - qualquer desvio no código é um bug.
hmijail lamenta os demitidos em 1/07/19
5

O código fonte do BufferedReader mostra que o subjacente está fechado quando você fecha o BufferedReader.

Brian Agnew
fonte
1
Eu realmente quero dar um joinha neste link para algo concreto, mas isso se refere apenas à implementação do OpenJDK e, como os JavaDocs não são claros Reader#close(), isso não fornece evidências concretas de que o Oracle JDK, por exemplo, foi implementado em um Moda semelhante.
searchengine27
4

Depois de verificar o código fonte, descobri que, por exemplo:

FileReader fReader = new FileReader(fileName);
BufferedReader bReader = new BufferedReader(fReader);

o método close () no objeto BufferedReader chamaria o método abstrato close () da classe Reader, que chamaria o método implementado na classe InputStreamReader , que então fecha o objeto InputStream .

Portanto, apenas bReader.close () é suficiente.

Anup Verma
fonte
4
O que o código-fonte mostra não pode ser citado como referência. É o que a especificação diz, neste caso, o Javadoc, em que se pode confiar.
Marquês de Lorne
1

A partir do Java 7, você pode usar a instrução try-with-resources

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
    return br.readLine();
}

Como a BufferedReaderinstância é declarada em uma instrução try-with-resource, ela será fechada, independentemente de a instrução try ser concluída normalmente ou abruptamente. Portanto, você não precisa fechá-lo na finallydeclaração. (Este também é o caso de instruções de recursos aninhados)

Esta é a maneira recomendada de trabalhar com recursos, consulte a documentação para obter informações mais detalhadas

Claudiu
fonte
Isso é quase idêntico à resposta da @ mcdowell de 2009, que também cobre alguns problemas que podem ocorrer.
tresf 10/02
0

Você só precisa fechar o bufferedReader, ou seja, reader.close () e ele funcionará bem.

Jitendra
fonte
0

Estou atrasado, mas:

BufferReader.java:

public BufferedReader(Reader in) {
  this(in, defaultCharBufferSize);
}

(...)

public void close() throws IOException {
    synchronized (lock) {
        if (in == null)
            return;
        try {
            in.close();
        } finally {
            in = null;
            cb = null;
        }
    }
}
Dmitry Gashko
fonte
Eeeeh que não responde a sua pergunta? Ela pergunta se é necessário fechar o FileReader e o BufferedReader, não um código de exemplo.
TornaxO7 7/01
@ TornaxO7 não, não é um código de exemplo. Acabei de escrever parte do código-fonte java. Portanto, se você clicar em alguma função do BufferedReader com a tecla ctrl / cmd (depende do IDE), poderá ver o código-fonte do BufferedReader e encontrar esse fragmento de código. Então, como você pode ver o BufferedReader, feche o FileReader por si só ('in' é FileReader nesse caso; portanto, quando você chama bufferReader.close (), chama in.close () por dentro, exatamente no método bufferReader.close)
Dmitry Gashko
0

Você não precisa fechar o leitor / gravador embrulhado.

Se você deu uma olhada nos documentos ( Reader.close(), Writer.close()), verá que Reader.close()ele diz:

Fecha o fluxo e libera todos os recursos do sistema associados a ele.

O que apenas diz que "libera quaisquer recursos do sistema associados a ele". Mesmo que não confirme ... ele dá uma cutucada para começar a olhar mais fundo. e se você for paraWriter.close() ele, apenas declara que se fecha.

Nesses casos, nos referimos ao OpenJDK para dar uma olhada no código fonte.

Na linha 265 do BufferedWriter , você verá out.close(). Portanto, não está se fechando .. É outra coisa. Se você procurar ocorrências na classe " out", notará que no construtor da Linha 87, que outé o escritor, a classe agrupa onde chama outro construtor e, em seguida, atribui outparâmetro à sua própria outvariável.

Então .. E os outros? Você pode ver um código semelhante nas linhas BufferedReader 514 , BufferedInputStream Line 468 e InputStreamReader Line 199 . Outros eu não sei, mas isso deve ser suficiente para supor que eles fazem.

Omar Abdul'Azeez
fonte