当stdout流可用时,从子流程中读取它



在我的Java应用程序中,我需要将一些脚本作为子流程来执行,并监控来自Java的stdout上的输出,以便在必要时对某些输出做出反应。

我使用apachecommons-exec生成子进程,并将已执行脚本的stdout重定向到输入流。

我遇到的问题是,当从流中读取时,Java进程会被阻塞,直到子进程完成执行。我不能等到子流程结束才对输出做出反应,但我需要在它可用时异步读取它。

下面是我的Java代码:

public class SubProcessReact {
    public static class LogOutputStreamImpl extends LogOutputStream {
        @Override
        protected void processLine(String line, int logLevel) {
            System.out.println("R: " + line);
        }
    }
    public static void main (String[] args) throws IOException, InterruptedException {
        CommandLine cl = CommandLine.parse("python printNumbers.py");
        DefaultExecutor e = new DefaultExecutor();
        ExecuteStreamHandler sh = new PumpStreamHandler(new LogOutputStreamImpl());
        e.setStreamHandler(sh);
        Thread th = new Thread(() -> {
            try {
                e.execute(cl);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        });
        th.start();
    }
}

在这个例子中,子流程是一个python脚本,它在输出之间有一秒的延迟向上计数,这样我就可以验证Java代码在数据进入时是否有响应

Python代码:

import time
for x in range(0,10):
    print x
    time.sleep(1)

我希望LogOutputStreamImpl在每一行出现时都打印它,但实际发生的是,它读取流块,直到子流程完成,然后打印所有输出。

我能做些什么让这件事按我的意愿进行吗?

为什么要使用第三方库来做Java SE已经做得很好的事情?就我个人而言,我更喜欢依赖尽可能少的外部库,以便使我的程序易于移植并减少故障点:

ProcessBuilder builder = new ProcessBuilder("python", "printNumbers.py");
builder.inheritIO().redirectOutput(ProcessBuilder.Redirect.PIPE);
Process process = builder.start();
try (BufferedReader reader = new BufferedReader(
    new InputStreamReader(process.getInputStream()))) {
    reader.lines().forEach(line -> System.out.println("R: " + line));
}
process.waitFor();

相关内容

  • 没有找到相关文章

最新更新