Em Java, quando eu chamo OutputStream.close () eu sempre preciso chamar OutputStream.flush () antes?

Se eu apenas chamar close() em um stream de saída, a saída é garantida ou preciso chamar flush() sempre?

Close () sempre libera, então não precisa ligar.

EDIT: Esta resposta é baseada no senso comum e todo o stream de saída que encontrei. Quem vai implementar um close () para um stream em buffer sem primeiro esvaziar o buffer? Não há nenhum dano em chamar o flush antes do close (). No entanto, existem consequências se flush () for chamado excessivamente. Pode derrotar abaixo do mecanismo de buffering.

Enquanto close deve chamar flush , é um pouco mais complicado do que isso …

Em primeiro lugar, decoradores (como BufferedOutputStream ) são comuns em Java. A construção do decorador pode falhar, então você precisa close o stream “bruto” em um bloco finally cuja try inclui o decorador. No caso de uma exceção, geralmente não é necessário close o decorador (exceto, por exemplo, para decoradores de compactação mal implementados). Você normalmente precisa flush o decorador no caso de não-exceção. Assim sendo:

 final RawOutputStream rawOut = new RawOutputStream(rawThing); try { final DecoratedOutputStream out = new DecoratedOutputStream(rawOut); // ... stuff with out within ... out.flush(); } finally { rawOut.close(); } 

Para completar, os methods close decorador são frequentemente implementados incorretamente. Isso inclui alguns em java.io até recentemente.

Claro, você provavelmente quer usar o idioma Execute Around para manter em DRY (ish).

Se você quiser que o stream seja liberado, então sim , chame flush() antes de chamar close() .

Apesar de todas as outras respostas ao contrário (mas como observado corretamente em alguns comentários), a implementação padrão de java.io.OutputStream::close() não chama flush() . De fato, não faz nada. Se você tem uma distribuição fonte, você pode facilmente verificar por si mesmo, caso contrário, apenas confie no javadoc oficial , citado aqui:

O contrato geral de fechamento é que fecha o stream de saída. Um stream fechado não pode executar operações de saída e não pode ser reaberto.

O método close do OutputStream não faz nada.

Independentemente de close() liberar ou não, a abordagem mais segura deve ser liberar manualmente. Se ficar corado de novo, quem se importa?

A resposta de “Tom Hawtin – tackline” tem detalhes adicionais sobre o fechamento seguro de streams (mas não responde a pergunta original claramente = P).

Há tantas respostas e comentários perigosos aqui. Continue lendo porque eu usei a palavra perigoso .

Primeiras coisas primeiro. Verifique isso.

  • AutoCloseable#close()
  • Closeable#close()
  • OutputStream#close()
  • Writer#close()

Você deve descobrir que não há uma declaração única dizendo que close() chamará flush() . Conserte-me se eu perdi alguma.

Use flush() sempre que precisar ou precisar garantir que os dados em buffer sejam liberados pelo menos no nível do sistema operacional.

flush() tem seu próprio propósito (s).

 // client // sends exactly 234 bytes // and returns exactly 124 bytes from the server static byte[] sendAndReceive(final OutputStream output, final InputStream input) throws IOException { final byte[] request = new byte[234]; output.write(request); // output.flush(); // @@? is this required or not? final byte[] response = new byte[124]; new DataInputStream(input).readFully(response); return response; } // server // recieve exactly 234 bytes from the client // sends exactly 124 bytes static void receiveAndSend(final InputStream input, final OutputStream output) throws IOException { final byte[] request = new byte[234]; new DataInputStream(input).readFully(request); final byte[] response = new byte[124]; output.write(response); // output.flush(); // @@? is this required or not? } 

As coisas podem ter mudado, mas eu experimentei por mim mesmo há uma década. O código-fonte acima (cliente) funcionou com o Windows XP e falhou com o Windows 2000 Server para um mesmo terminal (servidor).

E (você) não precisa (depende) de qualquer comportamento específico de implementação de close() .

 static void writeFile(File file, byte[] bytes) throws IOException { try (OutputStream out = new FileOutputStream(bytes)) { out.write(bytes); out.flush(); // who cares what FileInputStream#close does? } } 

Note, também, que o flush() não significa escrever / enviar seus dados para o disco físico ou ponto de extremidade remoto. Ele, na maioria das vezes, apenas libera os dados armazenados em buffer na JVM no sistema operacional subjacente.


errata

Writer#close() explicitamente diz que

fecha o stream, liberando-o primeiro.

Mas isso não significa que todas as subclasss mantêm esse contrato raiz. Veja PrintWriter#close() que (sem flush() ) fecha a out interna ( Writer ), o que, novamente, depende da out de close() .

Os streams representam resources que você deve sempre limpar explicitamente, chamando o método de fechamento. Algumas classs java.io (aparentemente apenas as classs de saída) incluem um método flush . Quando um método close é chamado em uma dessas classs, ele executa automaticamente um flush. Não há necessidade de chamar explicitamente o flush antes de fazer o fechamento .