在 java 中读取进程的实时输出
Read live output of process in java
我在 java 应用程序中使用
启动了一个 python 脚本
Process p = Runtime.getRuntime().exec("python script.py");
此脚本循环运行,仅由事件(或用户交互)取消。该脚本在每个循环周期写入输出,一些文本如“12:22:35 -- Heartbeat”
while True:
print("Heartbeat")
time.sleep(1)
在我的 Java 应用程序中,我想读取显示的输出。我的问题是,如果我使用 BufferReader,它将等到进程完成,然后读取输出。以下是我的阅读方式:
BufferedReader is = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = is.readLine()) != null)
System.out.println(line);
如何读取输出 "live"?
为了更好地理解:python-脚本侦听硬件按钮,按下此按钮时,会写出一些输出。在我的 java 应用程序中,我想显示此消息并将其发送给一些客户。
我经常写这样的东西:
class StreamHandler extends Thread {
InputStream is;
Writer writer;
StreamHandler(InputStream is, Writer writer) {
super("StreamHandler");
this.is = is;
this.writer = writer;
}
@Override
public void run() {
try (InputStreamReader isr = new InputStreamReader(is)) {
char buffer[] = new char[256];
int n;
while ((n = isr.read(buffer)) > 0) {
writer.write(buffer, 0, n);
}
} catch (IOException e) {
System.err.println("StreamHandler: " + e);
}
}
}
虽然我使用它来将输出流捕获到我自己的缓冲区,但您可以简单地实时回显 stdout
,例如:
Process process = Runtime.getRuntime().exec(...);
Writer writer = new OutputStreamWriter(System.out);
StreamHandler stdout_handler = new StreamHandler(process.getInputStream(), writer);
stdout_handler.start();
使用https://github.com/zeroturnaround/zt-exec
new ProcessExecutor().command("python", "script.py")
.redirectOutput(new LogOutputStream() {
@Override
protected void processLine(String line) {
...
}
})
.execute();
尝试将您的 python 代码更改为:
while True:
print("Heartbeat", flush=True)
time.sleep(1)
我一直在尝试和你做同样的事情,并找到了这个问题的解决方案:PumpStreamHandler can capture the process output in realtime
如果你只想打印到当前进程的流,那么你可以使用ProcessBuilder
class创建一个进程并让它“继承”IO流像这样:
Process process = new ProcessBuilder()
.command(commandList)
.directory(workingDirectory)
.inheritIO()
.start();
或者,如果您想更好地控制流,
Process process = new ProcessBuilder()
.command(commandList)
.directory(workingDirectory)
.redirectOutput(ProcessBuilder.Redirect.INHERIT)
.redirectInput(ProcessBuilder.Redirect.INHERIT)
.redirectError(ProcessBuilder.Redirect.INHERIT)
.start();
同样,这可能适用于您的情况,也可能不适用,这取决于程序所在的终端 运行。我已经在系统终端中使用 java 程序尝试了 运行 mysql
和 python
命令行解释器,它工作正常。
但是如果你想将输出重定向到其他地方,那么来自进程的标准输出将被缓冲(参见 here)。在您的情况下,缓冲区仅在程序完成期间被刷新。因此,在 print
中设置 flush=True
就像答案中提到的@Mateus Terra 可能会起作用。
我在 java 应用程序中使用
启动了一个 python 脚本Process p = Runtime.getRuntime().exec("python script.py");
此脚本循环运行,仅由事件(或用户交互)取消。该脚本在每个循环周期写入输出,一些文本如“12:22:35 -- Heartbeat”
while True:
print("Heartbeat")
time.sleep(1)
在我的 Java 应用程序中,我想读取显示的输出。我的问题是,如果我使用 BufferReader,它将等到进程完成,然后读取输出。以下是我的阅读方式:
BufferedReader is = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = is.readLine()) != null)
System.out.println(line);
如何读取输出 "live"?
为了更好地理解:python-脚本侦听硬件按钮,按下此按钮时,会写出一些输出。在我的 java 应用程序中,我想显示此消息并将其发送给一些客户。
我经常写这样的东西:
class StreamHandler extends Thread {
InputStream is;
Writer writer;
StreamHandler(InputStream is, Writer writer) {
super("StreamHandler");
this.is = is;
this.writer = writer;
}
@Override
public void run() {
try (InputStreamReader isr = new InputStreamReader(is)) {
char buffer[] = new char[256];
int n;
while ((n = isr.read(buffer)) > 0) {
writer.write(buffer, 0, n);
}
} catch (IOException e) {
System.err.println("StreamHandler: " + e);
}
}
}
虽然我使用它来将输出流捕获到我自己的缓冲区,但您可以简单地实时回显 stdout
,例如:
Process process = Runtime.getRuntime().exec(...);
Writer writer = new OutputStreamWriter(System.out);
StreamHandler stdout_handler = new StreamHandler(process.getInputStream(), writer);
stdout_handler.start();
使用https://github.com/zeroturnaround/zt-exec
new ProcessExecutor().command("python", "script.py")
.redirectOutput(new LogOutputStream() {
@Override
protected void processLine(String line) {
...
}
})
.execute();
尝试将您的 python 代码更改为:
while True:
print("Heartbeat", flush=True)
time.sleep(1)
我一直在尝试和你做同样的事情,并找到了这个问题的解决方案:PumpStreamHandler can capture the process output in realtime
如果你只想打印到当前进程的流,那么你可以使用ProcessBuilder
class创建一个进程并让它“继承”IO流像这样:
Process process = new ProcessBuilder()
.command(commandList)
.directory(workingDirectory)
.inheritIO()
.start();
或者,如果您想更好地控制流,
Process process = new ProcessBuilder()
.command(commandList)
.directory(workingDirectory)
.redirectOutput(ProcessBuilder.Redirect.INHERIT)
.redirectInput(ProcessBuilder.Redirect.INHERIT)
.redirectError(ProcessBuilder.Redirect.INHERIT)
.start();
同样,这可能适用于您的情况,也可能不适用,这取决于程序所在的终端 运行。我已经在系统终端中使用 java 程序尝试了 运行 mysql
和 python
命令行解释器,它工作正常。
但是如果你想将输出重定向到其他地方,那么来自进程的标准输出将被缓冲(参见 here)。在您的情况下,缓冲区仅在程序完成期间被刷新。因此,在 print
中设置 flush=True
就像答案中提到的@Mateus Terra 可能会起作用。