子进程刷新的Java输出流导致IOException

时间:2015-01-04 07:58:51

标签: java exception stream output flush

我有一个子进程逐行接收来自stdin的数据。然后它接收$X$行,它停止读取输入流,在其上执行内部任务,然后退出。 现在我为它写了一些测试器:

public class MessageShowTester {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException {
        Process p = Runtime.getRuntime().exec("java -jar \"/home/user/NetBeansProjects/MessageShow/dist/MessageShow.jar\"");
        p.getOutputStream().write("Hi\n$X$\n".getBytes());
        p.getOutputStream().flush();

    }

}

结果我在IOException行收到了p.getOutputStream().flush()。更奇怪的是,我使用相同构造的另一个应用程序并没有分享这种行为。

作为示例,MessageShow的版本有限,在测试人员上失败的方式相同,但在IDE中运行良好。

public class MessageShow {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        String message="";
        String temp="";

        while(true)
        {
            temp = new Scanner(System.in).nextLine();


            if("$X$".equals(temp)) break;


                message+=temp;
                message+="\n";


        }


        JOptionPane.showMessageDialog(null, message);
    }

}

堆栈追踪:

Exception in thread "main" java.io.IOException: Broken pipe
    at java.io.FileOutputStream.writeBytes(Native Method)
    at java.io.FileOutputStream.write(FileOutputStream.java:315)
    at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
    at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
    at messageshowtester.MessageShowTester.main(MessageShowTester.java:23)
Java Result: 1

1 个答案:

答案 0 :(得分:1)

如果子流程快速完成,则父进程可能尚未完成刷新。在这种情况下,进程之间的管道已在子进程端关闭,您将看到

 Exception in thread "main" java.io.IOException: Stream closed

或类似。

您不应该需要显式刷新。要将单行传递给子流程,请考虑流程参数。

对什么有效,什么无效有信心,但我发现使用

    PrintWriter pw = new PrintWriter( p.getOutputStream() );
    pw.println("hifile.dat");
    pw.println("$X$");
    pw.close();

成功将两行传递给子流程。

在子流程中,

 Scanner scanner = new Scanner(System.in);
 while(true){
    temp = scanner.nextLine();
    if("$X$".equals(temp)) break;
    message+=temp;
}

比为每一行重新创建一个扫描器更好,尽管它不会影响子流程的命运。