Pergunta

Depois de fornecer algumas respostas aqui, e ler alguns comentários, parece que, na prática IOException nunca é jogado numa estreita para o arquivo I / O.

Existem casos em que chamando perto em um Stream / leitor / gravador de fato lança uma IOException?

Se uma exceção é realmente jogado, como deve ser tratada?

Foi útil?

Solução

Para arquivos, você pode não ver IOException jogado muitas vezes em close (), mas você definitivamente vai vê-lo por falta de arquivo I / O como fechar soquetes à rede.

Aqui está um exemplo de um bug Java onde fechando um soquete UDP eventualmente, causou um IOException para ser jogado.

Outras dicas

Eu encontrei dois casos:

  • Perder a conexão de rede enquanto ainda houver dados no buffer para ser liberado.
  • Tendo o sistema de arquivos encher-se (ou atingir o seu limite de usuários para o tamanho do arquivo) quando ainda houver dados no buffer para ser liberado.

Ambos os exemplos depender de algo acontecer enquanto ainda há dados no buffer. Fechar libera o buffer antes que o arquivo é fecha, por isso, se há um erro ao escrever os dados para o arquivo ele lança uma IOException.

Se você executar o código a seguir passando o nome de um arquivo para criar em uma unidade de rede e, em seguida, antes de pressionar a entrar desligue chave o seu cabo de rede, ele fará com que o programa para lançar uma IOException em estreita.

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class Test
{
    public static void main(final String[] argv)
    {
        final File file;

        file = new File(argv[0]);
        process(file);
    }

    private static void process(final File file)
    {
        Writer writer;

        writer = null;

        try
        {
            writer = new FileWriter(file);
            writer.write('a');
        }
        catch(final IOException ex)
        {
            System.err.println("error opening file: " + file.getAbsolutePath());
        }
        finally
        {
            if(writer != null)
            {
                try
                {
                    try
                    {
                        System.out.println("Please press enter");
                        System.in.read();
                    }
                    catch(IOException ex)
                    {
                        System.err.println("error reading from the keyboard");
                    }

                    writer.close();
                }
                catch(final IOException ex)
                {
                    System.err.println("See it can be thrown!");
                }
            }
        }
    }
}

Desde Java 7 você pode usar try-com-recursos para sair dessa bagunça (código explícito geração exceção removidos para a operação close()):

private static void process(final File file) {
    try (final Writer writer = new FileWriter(file)) {
        writer.write('a');
    } catch (final IOException e) {
        // handle exception
    }
}

este irá lidar com auto-magicamente as exceções em close() e ele realiza uma verificação null explícita internamente.

Quando isso acontece, ele deve ser tratado como qualquer outro IOException, não ignorado como você vê recomendada tantas vezes. A suposição é, eu acho, que desde que você é feito usando o fluxo, não importa se ele foi feita corretamente.

No entanto, a limpeza adequada é importante. Se uma operação de close() faz levantar uma exceção, é bem provável que envolveu liberando uma certa saída, cometer alguma transação (no caso de uma conexão de banco de dados que você pensou que era somente leitura), etc.-definitivamente não é algo que deve ser ignorado. E, uma vez que é raro, você não comprometer a confiabilidade de sua aplicação de forma significativa por abortar a operação.

É especificamente FileInputStream.close que não jogue, mesmo se o disco rígido está em chamas. Presumivelmente é o mesmo para a entrada de soquete. Para saída córregos você também pode ser rubor. Até há relativamente pouco [ver timestamps] BufferedOutputStream usado para deixar de fechar o fluxo subjacente se flush jogou.

(@ MaartenBodewes gostaria de me apontar que FileInputStream.close não jogar não é especificado pelos docs API. Na época do post era costume elide a cláusula mencionando que esta relacionado com o Sun JDK (agora conhecido como o Oracle JDK e OpenJDK). parece que um ex-reimplementação obscura chamada Apache Harmony, que Android usado para uso pode ter tido um comportamento diferente. potencialmente outras implementações, ou versões do OpenJDK, também pode jogar.)

Um exame do que pode acontecer quando chamar perto, como esconderijo exceção pode afetar você eo que você pode fazer sobre ele: Blog Post .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top