首页 > 解决方案 > 解析子进程的输出

问题描述

在 Java 中,我正在启动一个子进程,如下所示:

String[] command = {"java", "-jar", jarPath};
Process childProcess = new ProcessBuilder().inheritIO().command(command).start();

我希望子进程Success!在某个时候打印到标准输出(如果事情成功的话)。如何定期(例如,每 5 秒)检查Success!输出中是否有一行由子进程创建?

标签: javamultithreadingstdoutchild-processprintln

解决方案


所以......这是一个相当复杂的问题,尽管仅仅问它可能并不明显。

我无法使用ProcessBuilder课程来做到这一点
(也许有更多经验的人可以使用该路线回答)

这是您需要做的:使用该类Runtime.getRuntime().exec(command)来运行您的命令。这使您可以轻松访问标准输入和标准错误流。

以下是您可以使用的通用完整类。

用法:

    final String jarPath = "jarPath.jar";
    final String[] command = { "java.exe", "-jar", jarPath };

    final CrossPlatformCommand childProcess = new CrossPlatformCommand();
    final int exitCode = childProcess.execute(command[0] + " " + command[1] + " " + command[2]);
    System.out.println("Parse child process output: " + childProcess.getInput());

输出:

Parse child process output: Success!

有一些注意事项:美元符号需要在 Linux 中转义。可能还有其他字符需要转义(这个还没有充分调查,如果你使用其他需要转义的字符,可能需要修改这个类。)

 public class CrossPlatformCommand
 {
    private static final String SHELL_LINUX = "/bin/bash";
 
    private static final int BUFFER_SIZE = 4096;
 
    private static final String OS_NAME = System.getProperty("os.name").toLowerCase(Locale.getDefault());
 
    private final StringBuffer error = new StringBuffer();
 
    private final StringBuffer input = new StringBuffer();
 
    public int execute(final String command) throws Exception
    {
        final int exitCode;
 
        if (OS_NAME.startsWith("windows"))
        {
            exitCode = executeWindows(command);
        }
        else
        {
            exitCode = executeLinux(command); // OS_NAME.startsWith("linux")
        }
 
        return exitCode;
    }
 
    public String getError()
    {
        return this.error.toString();
    }
 
    public String getInput()
    {
        return this.input.toString();
    }
 
    private int executeLinux(final String command) throws Exception
    {
        final Process proc = Runtime.getRuntime().exec(SHELL_LINUX);
        processLinuxCommand(proc, command);
        return processStreams(proc);
    }
 
    private int executeWindows(final String command) throws Exception
    {
        final Process proc = Runtime.getRuntime().exec(command);
        return processStreams(proc);
    }
 
    private static void processLinuxCommand(final Process proc, final String command) throws Exception
    {
        try (BufferedWriter out = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())))
        {
            // Dollar signs are special in Linux.
            out.write(command.replace("$", "\\$"));
 
            out.newLine();
            out.flush();
        }
    }
 
    private int processStreams(final Process proc) throws Exception
    {
        fillBuffer(proc.getInputStream(), this.input);
        fillBuffer(proc.getErrorStream(), this.error);
        return proc.waitFor();
    }
 
    private static void fillBuffer(final InputStream in, final StringBuffer sb) throws IOException
    {
        sb.setLength(0);
 
        final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        final char[] buffer = new char[BUFFER_SIZE];
        final int length = reader.read(buffer);
        for (int i = 0; i < length; i++)
        {
            sb.append(buffer[i]);
        }
    }
 }
 

推荐阅读