Закрытие Входных Потоков 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 ответов:
примеры в Самоучитель Свойства закрыть
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()
закрыть поток, например:
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
и затем вы просто используете свой обернутый экземпляр, и он автоматически закрывается, как только достигнут конец ввода или когда поток явно закрыт, в зависимости от того, что происходит первым.