2012-11-15 3 views
1

решена, Короче говоря, проблема заключалась в том, что я писал в уже закрыт FileOutputStreamFileOutputStream: поток закрыт

Я заметил, что некоторые странные семантику, используя класс FileOutputStream.

Если я создаю FileOutputStream, используя этот код:

try { 
    File astDumpFile = new File(dumpASTPath); 
    if(!astDumpFile.exists()) { 
     astDumpFile.createNewFile(); 
    } 
    astDumpStream = new FileOutputStream(dumpASTPath); 
} catch(IOException e) { 
    dumpAST = false; 
    //throw new IOException("Failed to open file for dumping AST: " + dumpASTPath); 
    System.out.println("Failed to open file for dumping AST: " + dumpASTPath); 
} 

в начале программы (astDumpStream является переменной-члена). Тогда, если я позже (~ 3 секунды) строка записи данных в файл, я получаю IOException: stream closed:

try { 
    String dotGraph = gpvisitor.getDotGraph(); 
    astDumpStream.write(dotGraph.getBytes("UTF8")); 
    astDumpStream.flush(); 
    astDumpStream.close(); 
} catch(IOException e) { 
    System.out.println("Failed to dump AST to file: " + e.getMessage()); 
    e.printStackTrace(); 
} 

Однако если скопировать excact код, который я использую для создания FileOutputStream непосредственно перед записью на него, он работает так, как ожидалось.

Теперь я задаюсь вопросом, почему я получаю это исключение, если я создаю этот объект раньше, но не если я создаю его непосредственно, прежде чем использовать его.

EDIT: Исключение:

java.io.IOException: Stream Closed 
    at java.io.FileOutputStream.writeBytes(Native Method) 
    at java.io.FileOutputStream.write(FileOutputStream.java:305) 
    at MyClass.function(MyClass.java:208) 

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

EDIT: Окружающая среда Информация:

[~]> lsb_release -a 
Distributor ID: Debian 
Description: Debian GNU/Linux testing (wheezy) 
Release:  testing 
Codename:  wheezy 
[~]> java -version 
java version "1.7.0_09" 
Java(TM) SE Runtime Environment (build 1.7.0_09-b05) 
Java HotSpot(TM) 64-Bit Server VM (build 23.5-b02, mixed mode) 
+1

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

+0

Также создание файла является излишним. FileOutputStream пытается создать файл и только выдает FileNotFoundException, если он не может: http://docs.oracle.com/javase/6/docs/api/java/io/FileOutputStream.html#FileOutputStream%28java.io.File% 29 –

+0

@Brendan Long: Это единственный код, доступ к которому имеет объект FileOutputStream. – smerlin

ответ

1

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

Чтобы избежать ошибок отступа, есть два хороших советов, которые я получил:

  • Всегда отступа последовательно. Предпочтительно использовать инструмент, который делает это для вас (например, Eclipse).
  • Всегда используйте фигурные скобки, даже если вы не считаете их нужными. Это помогает предотвратить немало мелких ошибок, которые навсегда найдут, поэтому дополнительная половина секунды, требуемая для ввода каждого из них, более чем компенсируется часами, которые вы не тратите на поиск этих ошибок.
4

Единственная причина, чтобы получить IOException жалуясь, что поток закрыт, потому что поток был закрыт. Вы должны будете проследить через свой код, чтобы узнать, где это происходит. Некоторые не столь очевидные места включают вызовы в другие методы и finally блоков try операторов. Другое дело - переназначить переменную astDumpStream в другой поток (который был закрыт до того, как IOException был поднят —, возможно, даже до первого присвоения astDumpStream).

Время не кажется актуальным, если у вас есть отдельный поток, который может закрыть поток после задержки.

+0

я не использую или не пользуюсь 'astDumpStream' вне фрагментов кода, которые я опубликовал, и' astDumpStream' является единственной ссылкой на этот объект потока. – smerlin

+0

@smerlin - Мне интересно, что-то происходит на уровне ОС. Является ли файл локализованным где-то странным (например, сетевой диск), где может быть какой-то тайм-аут в базовом потоке? –

+0

Поскольку я тестировал это на компьютере в своем университете, и поскольку домашние каталоги этих машин являются сетевыми ресурсами, я снова тестировал это в локальном каталоге этого компьютера ('/ tmp'). Однако проблема все еще происходила. – smerlin

0

В Second Tedd - в случае, если вы используете вложенную попытку с блоком ресурсов и используете поток вне tryblock - вы можете запускать и в этой ситуации, потому что, как только элемент управления выходит из вложенного try с блоком ресурсов, поток будет закрыт.

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