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

但是,如果我FileOutputStream在写入之前直接复制用于创建 to 的精确代码,它会按预期工作。

现在我想知道如果我早先创建该对象为什么会出现该异常,但如果我在使用它之前直接创建它就不会。

编辑:例外:

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要寻找的另一件事是将变量重新分配astDumpStream给不同的流(在IOException引发之前关闭 - 甚至可能在第一次分配给之前astDumpStream)。

除非您有一个单独的线程可能会在延迟后关闭流,否则时间似乎并不相关。

于 2012-11-15T19:44:37.017 回答
1

如果close()函数被多次调用,则可能发生这种情况的唯一方法。我的猜测是,由于某种原因,第二个代码块被多次调用。

为了防止缩进错误,我收到了两条很好的建议:

  • 始终一致地缩进。最好使用为您执行此操作的工具(如 Eclipse)。
  • 始终使用花括号,即使您认为不需要它们。这有助于防止一些需要永远找到的小错误,因此键入每个错误所需的额外半秒时间远远超过了您不花时间寻找这些错误的时间。
于 2012-11-15T23:48:25.540 回答
0

对于第二个 Tedd - 如果您碰巧使用资源块的嵌套尝试并在 tryblock 之外使用流 - 您也可以在这种情况下运行,因为一旦控制脱离资源块的嵌套尝试,流将被关闭。

于 2014-02-10T15:54:16.200 回答