Закрытие Java InputStreams - PullRequest
       5

Закрытие Java InputStreams

62 голосов
/ 22 октября 2010

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

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

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

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 ]

46 голосов
/ 22 октября 2010

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

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

Одним из улучшений, которое вы можете сделать, является использование IOUtils.closeQuietly ()

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

Properties props = new Properties();
InputStream fis = new FileInputStream("message.properties");
try {
    props.load(fis);
    //omitted.
} catch (Exception ex) {
    //omitted.
} finally {
    IOUtils.closeQuietly(fis);
}
30 голосов
/ 28 июля 2014

Я бы пошел с попыткой с ресурсами (по крайней мере для Java 7+):

Properties props = new Properties();

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

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

25 голосов
/ 22 октября 2010

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

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

Только для справки, я проверил реализацию Apache Harmony Свойства , и он не закрывает поток при загрузке.

13 голосов
/ 22 октября 2010

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

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

12 голосов
/ 09 июля 2015

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

try(InputStream is = new FileInputStream("message.properties")) {
    // ...
}
7 голосов
/ 22 октября 2010

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

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

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

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

2 голосов
...