0

解決済み、要するに: 問題は、既に閉じられている FileOutputStream に書き込んだことでした

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();
}

ただし、 to を作成するために使用する exact コードを、書き込みの直前にコピーするFileOutputStreamと、期待どおりに機能します。

そのオブジェクトを以前に作成すると例外が発生するのに、使用する直前に作成すると例外が発生しないのはなぜだろうか。

編集:例外:

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すべてが正しく記述されますが、それでも例外が発生します。

編集: 環境情報:

[~]> 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)
4

3 に答える 3

4

ストリームが閉じられたという不平を得る唯一の理由IOExceptionは、ストリームが閉じられたためです。コードをトレースして、それがどこで発生しているかを調べる必要があります。あまり目立たない場所には、他のメソッドやステートメントfinallyのブロックへの呼び出しが含まれています。try探すべきもう 1 つのことはastDumpStream、別のストリームへの変数の再割り当てです (これは、 が発生する前に閉じられました。IOExceptionおそらく への最初の割り当ての前でもastDumpStream)。

遅延後にストリームを閉じる可能性のある別のスレッドがない限り、時間は関係ないようです。

于 2012-11-15T19:44:37.017 に答える
1

これが発生する唯一の方法は、close()関数が複数回呼び出される場合です。私の推測では、何らかの理由で、コードの 2 番目のブロックが複数回呼び出されていると思われます。

インデント エラーを防ぐために、私が受け取った 2 つの良いアドバイスがあります。

  • 常に一貫してインデントします。できれば、これを行うツール (Eclipse など) を使用してください。
  • 中括弧が必要ないと思われる場合でも、常に中括弧を使用してください。これは、見つけるのに永遠にかかるかなりの数の小さなバグを防ぐのに役立ちます。そのため、それぞれを入力するのにかかる余分な 0.5 秒は、これらのバグを探すのに費やさない時間よりも多くなります。
于 2012-11-15T23:48:25.540 に答える
0

2番目のTeddへ-リソースブロックでネストされたtryを使用し、tryblockの外部でストリームを使用する場合-リソースブロックでネストされたtryからコントロールが出るとストリームが閉じられるため、この状況でも実行できます。

于 2014-02-10T15:54:16.200 に答える