java - 解析子进程的输出
问题描述
在 Java 中,我正在启动一个子进程,如下所示:
String[] command = {"java", "-jar", jarPath};
Process childProcess = new ProcessBuilder().inheritIO().command(command).start();
我希望子进程Success!
在某个时候打印到标准输出(如果事情成功的话)。如何定期(例如,每 5 秒)检查Success!
输出中是否有一行由子进程创建?
解决方案
所以......这是一个相当复杂的问题,尽管仅仅问它可能并不明显。
我无法使用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]);
}
}
}
推荐阅读
- selenium - Selenium Test 在虚拟机上速度较慢,mvn build 速度较快
- wpf - 在任何字符上换行,而不仅仅是单词边界
- terminal - 如何通过 ifconfig 找到我的 MAC 地址。Ubuntu
- excel - 是否可以创建一个按钮激活的宏来在一个单元格中执行累积和然后每次按下按钮时自行循环
- azure - 我可以在没有公共 IP 的情况下为 Azure VM 提供 Internet 访问权限吗?
- python - 将字节 csv 字符串转换为 pandas 数据帧
- sql - 如何将另一列的值赋予表函数的参数?(或者,具有多个 table_names 的 Snowflake copy_history)
- r - R Shiny - 在更新相互依赖的输入时了解观察和观察事件之间的区别
- jquery - Laravel - 如何使用 jQuery 使用 keyup 验证 Laravel 文本输入
- python - os.listdir 只显示隐藏文件?