Зачем мне заботиться об исключениях IOException, когда файл закрыт?

Я видел такие вещи в коде Java довольно часто...

try
{
    fileStream.close();
}
catch (IOException ioe)
{
    /* Ignore. We do not care. */
}

Это разумно или кавалер?

Когда бы я заботился о том, что закрытие файла не удалось? Каковы последствия игнорирования этого исключения?

3 ответа

Решение

Я бы как минимум зарегистрировал исключение.

Я видел, как это иногда случалось, если попытка закрыть файл не удалась из-за невозможности сброса данных. Если вы просто проглотите исключение, вы потеряете данные, не осознавая этого.

В идеале, вам, вероятно, следует проглотить исключение, если вы уже находитесь в контексте другого исключения (т.е. вы находитесь в блоке finally, но из-за другого исключения, а не после завершения блока try), но выбросить его, если ваша операция выполняется иначе успешный. К сожалению, это несколько уродливо, чтобы разобраться:(

Но да, вы должны хотя бы войти в систему.

Вам было бы все равно, если close() Метод сбрасывает записанное содержимое из буфера в файловую систему, и это не удается. например, если файл, в который вы пишете, находится в удаленной файловой системе, которая стала недоступной.

Обратите внимание, что выше ре. сброс применяется ко всем выходным потокам, а не только к файлам

Наиболее распространенными проблемами close() являются нехватка дискового пространства или, как упомянул Брайан, удаленный поток, который потерял свою актуальность.

НОТА:

Вы должны действительно увидеть что-то вроде (примечание: я не проверял это)

SomeKindOfStream stream = null;
Throwable pending = null;
try {
    stream = ...;
    // do stuff with stream

} catch (ThreadDeath t) {
    // always re-throw thread death immediately
    throw t;

} catch (Throwable t) {
    // keep track of any exception - we don't want an exception on
    //   close() to hide the exceptions we care about!
    pending = t;

} finally {
    if (stream != null)
        try {
            stream.close();
        } catch (IOException e) {
            if (pending == null)
                pending = e;
        }
    }
    if (pending != null) {
        // possibly log - might log in a caller
        throw new SomeWrapperException(pending);
          // where SomeWrapperException is unchecked or declared thrown
    }
}

Почему все это?

Помните, что Java может отслеживать только одно "ожидающее" исключение за раз. Если тело основного блока try выдает исключение, а метод close() в finally выдает исключение, единственное, о чем вы будете знать, - это close().

Вышеуказанная структура делает следующее:

  • Следите за любым бросаемым броском в теле попытки
  • В случае, если это исключение - смерть потока, немедленно отбросьте его!
  • При закрытии, если у нас нет ожидающего исключения, отследите исключение закрытия; в противном случае ранее созданное исключение должно отслеживаться. (В этом случае вам, вероятно, следует попытаться записать ошибку close())
  • В конце, если есть ожидающее исключение, разберитесь с ним. Я обычно оборачиваю это и перебрасываю это. Лично я использую непроверенную оболочку, поэтому мне не нужно, чтобы все вызывающие в цепочке вызовов объявляли броски.

Чтобы выполнить вышеизложенное, я обычно использую шаблон метода шаблона для создания управления исключениями, а затем перезаписываю метод doWork(), который является телом try.

Другие вопросы по тегам