【问题标题】:Execute external process from java. Got the output after the process terminated, but need it before termination从java执行外部进程。进程终止后得到输出,但在终止前需要它
【发布时间】:2011-07-19 02:44:28
【问题描述】:

为什么我在进程终止后得到进程的输出?我需要在进程运行时而不是在进程终止后获取进程输出“实时”。我想运行一个像 jboss 这样的进程,它正在登录标准输出,所以我需要及时的信息,而不是在进程终止之后。谢谢你的回答。

这是我的代码:

        try {
        process = processBuilder.start();
        processOutput = process.getOutputStream();
        processInput = process.getInputStream();
        processReader = new BufferedReader(new InputStreamReader(
                processInput));
        processWriter = new BufferedWriter(new OutputStreamWriter(
                processOutput));

        while ((line = processReader.readLine()) != null) {
            System.out.println(line);
          }
        processReader.close();

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

扩展名:

所以我想通过一个带有按钮的 Eclipse 插件运行一个外部程序。当我单击按钮时,程序启动并且外部程序的输出将返回到控制台。当我单击停止时,程序停止。所以这就是我如何制作流程构建器的实例。我做了一个示例类来测试流程构建器,而无需在每次修改时启动整个插件项目。

这是我实现 Runnable 的流程构建器实例:

@Override
public void run() {
    List<String> command = new ArrayList<String>();
    command.add(serverPath);
    command.add(String.valueOf(count));
    command.add(filePath);
    processBuilder = new ProcessBuilder(command);
    processBuilder.redirectErrorStream(true);

    try {
        process = processBuilder.start();
        processOutput = process.getOutputStream();
        processInput = process.getInputStream();
        processReader = new BufferedReader(new InputStreamReader(
                processInput));
        processWriter = new BufferedWriter(new OutputStreamWriter(
                processOutput));

        System.out.println(process.waitFor());
        while ((line = processReader.readLine()) != null) {
            System.out.println(line);

        }
        processReader.close();

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

参数来自构造函数。这是实例化:

public static void main(String[] args) throws Exception

{

 SimulationProcess smp = new SimulationProcess(count, "file",
            "program_name");
    smp.run();

}

【问题讨论】:

    标签: java process live execution


    【解决方案1】:

    您可以尝试一些方法来解决您的问题:

    a) 制作一个测试程序并使用上面的代码运行它,以确保您可以正确阅读它。例如:

    public static void main(String[] args) {
      for(;;) {
        try {
          Thread.sleep(5000);
          System.out.println("Test output");
        } catch(InterruptedException e) {
          // Ignore
        }
    
      }
    }
    

    b) 确保您正在处理进程的错误流 - 如果您不处理错误流,进程可能会锁定。查看this site 获取有关使用 Java 的 ProcessBuilder 或 Runtime.exec() 时要避免的事情的教程 - 它包括 StreamGobbler 的实现,它将丢弃您不关心的流上的所有数据。

    c) 尝试使用System.out.flush() - 可能是您的输出正在被缓冲。

    编辑:感谢您的更新。你的问题就在这里:

    System.out.println(process.waitFor()); // Waits for the process to exit.
    while ((line = processReader.readLine()) != null) {
        System.out.println(line);
    }
    

    如果您删除 waitFor(),它将继续打印,直到流关闭。仅当进程终止时,流才应关闭。你应该把waitFor()放在循环后面吗?

    【讨论】:

    • 您好,感谢您的回答。现在我用一个简单的程序尝试它,仅此代码。我用 processBuilder.redirectErrorStream(true);所以我不必处理错误流。我尝试使用 Syso.flush,但它不起作用。我确保代码正常工作,因为进程已启动,当我手动停止它或导致终止进程的事件时,我将输出输出到控制台而没有错误。
    • 那么,即使使用像我上面的那个非常简单的程序,它在退出后仍然会输出吗?你是如何执行程序的?您能否更新一下您如何设置 ProcessBuilder 实例的问题?
    • 我按照您的要求扩展了我的问题。抱歉回复晚了,但我离开了一个星期。
    • 我已经编辑了我的答案。您的代码正在按照您的要求执行!你告诉waitFor()在打印任何东西之前退出进程。
    • while 循环之前的 System.out.flush() 为我做了。
    【解决方案2】:

    也许你的输出不包含换行符,这样你的 while 循环在进程完成之前不会做任何事情。

    尝试使用另一种不等待换行符的读取方法,例如:

    char[] cbuf = new char[10];
    while(processReader.read(cbuf) != -1)
    {
      System.out.print(cbuf);
    }
    

    【讨论】:

    • 我检查了你的答案,但它还没有工作。我尝试增加 cbuf 的大小,但这种方式也不起作用。无论如何,谢谢你的回答。
    猜你喜欢
    • 1970-01-01
    • 2020-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-16
    相关资源
    最近更新 更多