2015-10-14 12 views
4

Как указано в заголовке, следует ли закрывать поток при повторном использовании переменной FileOutputStream? Например, в следующих кодах я должен позвонить outfile.close(), прежде чем назначить ему новый файл и почему?Должен ли я закрывать поток при повторном использовании FileOutputStream?

Спасибо :)

FileOutputStream outfile = null; 
int index = 1; 

while (true) { 

    // check whether we should create a new file 
    boolean createNewFile = shouldCreateNewFile(); 

    //write to a new file if pattern is identified 
    if (createNewFile) { 
     /* Should I close the outfile each time I create a new file? 
     if (outfile != null) { 
      outfile.close(); 
     } 
     */ 
     outfile = new FileOutputStream(String.valueOf(index++) + ".txt"); 
    } 

    if (outfile != null) { 
     outfile.write(getNewFileContent()); 
    } 

    if (shouldEnd()) { 
     break; 
    } 
} 

try { 
    if (outfile != null) { 
     outfile.close(); 
    } 
} catch (IOException e) { 
    System.err.println("Something wrong happens..."); 
} 
+1

* «прежде чем я присвоить ему новый файл» * - Да, вы можете оставить изменения в буфере, а это означает, что они не могут быть сохранены в файл. Вы потребляете дескрипторы файлов, которые ограничены ресурсами в ОС. Вы занимаете ресурсы в своей JVM. Вы должны всегда приводить в порядок после себя.Взгляните на [Заявление о попытках с ресурсами] (https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) для лучшего решения для обработки закрываемых ресурсов – MadProgrammer

ответ

1

Я думаю, что путаница здесь вращается вокруг концепции «повторного использования» FileOutputStream. То, что вы делаете, - это просто повторное использование идентификатора (имя outfile вашей переменной), связав с ним новое значение. Но это имеет синтаксический смысл для компилятора Java. Объект именуемый по имени - FileOutputStream - просто выпадает на пол и в конечном итоге будет мусором, собранным в неуточненный более поздний момент времени. Неважно, что вы делаете с переменной, которая когда-то называлась. Если вы переадресовываете его еще FileOutputStream, установите его на null или позвольте ему выйти из сферы действия - все равно.

Вызов close явно сбрасывает все буферные данные в файл и освобождает связанные ресурсы. (Сборщик мусора будет выпускать их тоже, но вы не знаете, когда это может произойти.) Обратите внимание, что close также может бросить IOException так что это действительно важно, что вы знаете точку, в которой операция пытался которой вы только, если вы звоните функция явно.

5

YES. Как только вы закончите с одним файлом (потоком), вы всегда должны его закрывать. Так что ресурсы, выделенные с файлом (поток) будет выпущен к операционной системе, как дескрипторы файлов, буфер и т.д.

Java Документация FileOutputStream.close()

Замыкает этот выходной файловый поток и освобождает все системные ресурсы, связанные с этот поток. Этот поток вывода файла больше не может использоваться для записи байтов.

Неотложные файловые дескрипторы могут даже привести к утечке ресурсов в программе java. Reference

2

Даже без автоматического управления ресурсами, или try-with-resources (смотри ниже), код может быть гораздо более удобным для чтения и надежно:

for (int index = 1; shouldCreateNewFile(); ++index) { 
    FileOutputStream outfile = new FileOutputStream(index + ".txt"); 
    try { 
    outfile.write(getNewFileContent()); 
    } 
    finally { 
    outfile.close(); 
    } 
} 

Однако Java 7 введен новый синтаксис для закрытия, что является более надежным и информативный в случае ошибок. С его помощью, ваш код будет выглядеть следующим образом:

for (int index = 1; shouldCreateNewFile(); ++index) { 
    try (FileOutputStream outfile = new FileOutputStream(index + ".txt")) { 
    outfile.write(getNewFileContent()); 
    } 
} 

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

Вы должны всегда использовать автоматическое управление ресурсами в Java 7 или выше.

Смежные вопросы