Закрытие Входных Потоков Java


у меня есть некоторые вопросы об использовании метода close() при использовании Java InputStreams. Из того, что я вижу и читаю от большинства разработчиков, вы всегда должны явно вызывать close() на InputStream, когда он больше не нужен. Но сегодня я изучал использование файла свойств Java, и каждый пример, который я нашел, имеет что-то вроде этого:

Properties props = new Properties();
try {
    props.load(new FileInputStream("message.properties"));
    //omitted.
} catch (Exception ex) {}

в приведенном выше примере нет способа явно вызвать close (), потому что InputStream недоступен после него предназначенный. Я видел много подобных применений входных потоков, хотя это, кажется, противоречит тому, что большинство людей говорят о явном закрытии. Я прочитал JavaDocs Oracle, и он не упоминает, если свойства.метод load () закрывает входной поток. Мне интересно, если это в целом приемлемо или если это предпочтительнее сделать что-то вроде следующего:

Properties props = new Properties();
InputStream fis = new FileInputStream("message.properties");
try {
    props.load(fis);
    //omitted.
} catch (Exception ex) {
    //omitted.
} finally {
    try {
        fis.close();
    } catch (IOException ioex) {
        //omitted.
    }
}

какой способ лучше и/или эффективнее? Или это действительно имеет значение?

7 59

7 ответов:

примеры в Самоучитель Свойства закрыть FileInputStream явно после загрузки, поэтому я думаю, что можно с уверенностью предположить, что load метод не несет ответственности за это, вы.

// create and load default properties
Properties defaultProps = new Properties();
FileInputStream in = new FileInputStream("defaultProperties");
defaultProps.load(in);
in.close();

просто для справки, я проверил Apache Harmony реализация свойства, а это не закройте поток при загрузке.

класс свойств обертывает входной поток в LineReader для чтения файла свойств. Поскольку вы предоставляете входной поток, вы несете ответственность за его закрытие.

второй пример является лучшим способом обработки потока на сегодняшний день, не полагайтесь на кого-то другого, чтобы закрыть его для вас.

одно улучшение, которое вы могли бы сделать, это использовать IOUtils.closeQuietly()

http://commons.apache.org/io/api-1.2/org/apache/commons/io/IOUtils.html#closeQuietly(java.io.InputStream)

закрыть поток, например:

Properties props = new Properties();
InputStream fis = new FileInputStream("message.properties");
try {
    props.load(fis);
    //omitted.
} catch (Exception ex) {
    //omitted.
} finally {
    IOUtils.closeQuietly(fis);
}

Я бы пошел с try-with-resources (по крайней мере, для Java 7+):

Properties props = new Properties();

try(InputStream fis = new FileInputStream("message.properties")) {
    props.load(fis);
    //omitted.
} catch (Exception ex) {
    //omitted.
}

вызов close () должен вызываться автоматически при выходе из блока try.

в документации не упоминается, что props.load закроет входной поток. Вы должны закрыть входной поток вручную в блоке finally, как вы предлагаете.

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

Если вы используете Java 7+ Вы можете использовать это:

try(InputStream is = new FileInputStream("message.properties")) {
    // ...
}

похоже, что первый пример кода заканчивается тем, что метод finalize в FileInputStream фактически закрывает файл. Я бы сказал, что ваш второй пример лучше, хотя в обоих случаях файл не будет закрыт.

есть случаи, такие как потоки байтов, где close ничего не делает и может быть опущен, иначе я думаю, что лучше явно закрыть файл в блоке finally. Если вы откроете его, вы его закроете.

на сайте Oracle есть книга под названием Производительность Платформы Java что обсуждает финализаторы в своем приложении, он говорит:

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

позвольте мне добавить кое-что к ответам других людей.

Если вы можете импортировать Apache Commons IO, вы могли бы использовать очень удобный AutoCloseInputStreamх классов: вы заворачиваете InputStream и затем вы просто используете свой обернутый экземпляр, и он автоматически закрывается, как только достигнут конец ввода или когда поток явно закрыт, в зависимости от того, что происходит первым.