Fechando streams de input em Java

Eu tenho o seguinte trecho de código em um bloco try / catch

InputStream inputstream = conn.getInputStream(); InputStreamReader inputstreamreader = new InputStreamReader(inputstream); BufferedReader bufferedreader = new BufferedReader(inputstreamreader); 

Minha pergunta é que quando eu tenho que fechar esses streams no bloco finally, eu tenho que fechar todos os 3 streams ou apenas fechar o befferedreader irá fechar todos os outros streams?

Por convenção, os streams de wrapper (que envolvem streams existentes) fecham o stream subjacente quando são fechados, portanto, só é necessário fechar o bufferedreader em seu exemplo. Além disso, normalmente é inofensivo fechar um stream já fechado, portanto, fechar todos os três streams não afetará.

Normalmente, é ok apenas fechar o stream mais externo, porque, por convenção, ele deve acionar os streams subjacentes.

Então normalmente o código se parece com isso:

 BufferedReader in = null; try { in = new BufferedReader(new InputStreamReader(conn.getInputStream())); ... in.close(); // when you care about Exception-Handling in case when closing fails } finally { IOUtils.closeQuietly(in); // ensure closing; Apache Commons IO } 

No entanto, pode haver casos raros em que um construtor de stream subjacente gera uma exceção onde o stream já está aberto. Nesse caso, o código acima não fechará o stream subjacente porque o construtor externo nunca foi chamado e in é nulo. Então o bloco finally não fecha nada deixando o stream subjacente aberto.

Desde o Java 7 você pode fazer isso:

  try (OutputStream out1 = new ...; OutputStream out2 = new ...) { ... out1.close(); //if you want Exceptions-Handling; otherwise skip this out2.close(); //if you want Exceptions-Handling; otherwise skip this } // out1 and out2 are auto-closed when leaving this block 

Na maioria dos casos, você não deseja Tratamento de Exceções quando é elevado durante o fechamento, portanto pule estas chamadas explícitas de close ().

Editar Aqui está algum código para os não-crentes, onde é substancial usar esse padrão. Você também pode gostar de ler o javadoc do Apache Commons IOUtils sobre o método closeQuietly () .

  OutputStream out1 = null; OutputStream out2 = null; try { out1 = new ...; out2 = new ...; ... out1.close(); // can be skipped if we do not care about exception-handling while closing out2.close(); // can be skipped if we ... } finally { /* * I've some custom methods in my projects overloading these * closeQuietly() methods with a 2nd param taking a logger instance, * because usually I do not want to react on Exceptions during close * but want to see it in the logs when it happened. */ IOUtils.closeQuietly(out1); IOUtils.closeQuietly(out2); } 

Usar o “conselho” do @ Tom deixará de ser aberto quando a criação do out2 uma exceção. Este conselho é de alguém falando It's a continual source of errors for obvious reasons. Bem, eu posso ser cego, mas não é óbvio para mim. Meu padrão é idiota em todos os casos de uso em que consigo pensar, enquanto o padrão de Tom é propenso a erros.

Fechando o mais externo é suficiente (ou seja, o BufferedReader ). Lendo o código-fonte do BufferedReader , podemos ver que ele fecha o Reader interno quando seu próprio método close é chamado:

 513 public void close() throws IOException { 514 synchronized (lock) { 515 if (in == null) 516 return; 517 in.close(); 518 in = null; 519 cb = null; 520 } 521 } 522 } 

Como regra geral, você deve fechar tudo na ordem inversa em que você os abriu.

Eu fecharia todos eles na ordem inversa da qual você os abriu, como se ao abri-los fosse empurrar o leitor para uma pilha e o fechamento iria tirar o leitor da pilha.

No final, depois de fechar tudo, a “pilha de leitores” deve estar vazia.

Você só precisa fechar o recurso real. Você deve fechar o recurso mesmo se a construção de decoradores falhar. Para saída, você deve liberar o object mais decorador no caso feliz.

Algumas complicações:

  • Às vezes, os decoradores são resources diferentes (algumas implementações de compactação usam o heap C).
  • Fechar os decoradores em casos tristes realmente causa flushes, com a consequente confusão, como não fechar o recurso subjacente.
  • Parece que o recurso subjacente é um URLConnection , que não possui um método de disconnect / close como tal.

Você pode considerar usar o idioma Execute Around para não ter que duplicar esse tipo de coisa.