Java 将进程输出重定向到标准输出
我希望在Groovy程序中执行foo.bat,并将结果进程的输出重定向到stdout。Java或Groovy代码示例都可以Java 将进程输出重定向到标准输出,java,groovy,Java,Groovy,我希望在Groovy程序中执行foo.bat,并将结果进程的输出重定向到stdout。Java或Groovy代码示例都可以 foo.bat可能需要几分钟才能运行并生成大量输出,因此我希望在生成输出后立即查看输出,不必等到进程完成后再立即查看所有输出。这使用了一个类,该类读取执行程序生成的所有输出,并将其显示在自己的标准输出中 class StreamGobbler extends Thread { InputStream is; // reads everything from
foo.bat可能需要几分钟才能运行并生成大量输出,因此我希望在生成输出后立即查看输出,不必等到进程完成后再立即查看所有输出。这使用了一个类,该类读取执行程序生成的所有输出,并将其显示在自己的标准输出中
class StreamGobbler extends Thread {
InputStream is;
// reads everything from is until empty.
StreamGobbler(InputStream is) {
this.is = is;
}
public void run() {
try {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line=null;
while ( (line = br.readLine()) != null)
System.out.println(line);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("javac");
//output both stdout and stderr data from proc to stdout of this process
StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream());
StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream());
errorGobbler.start();
outputGobbler.start();
proc.waitFor();
如果您只是尝试获取一个简单命令的输出,那么这里有一个稍微简单的方法。如果您希望并行处理,或者如果您的命令接受stdin或生成stderr,则需要像jitter那样使用线程 如果要获得大量输出,请使用缓冲副本(如)
import java.io.*;
public class test {
static void copy(InputStream in, OutputStream out) throws IOException {
while (true) {
int c = in.read();
if (c == -1) break;
out.write((char)c);
}
}
public static void main(String[] args) throws IOException, InterruptedException {
String cmd = "echo foo";
Process p = Runtime.getRuntime().exec(cmd);
copy(p.getInputStream(), System.out);
p.waitFor();
}
}
以下Groovy代码将执行foo.bat并将输出发送到stdout:
println "foo.bat".execute().text
异步方式来实现它
void inputStreamToOutputStream(final InputStream inputStream, final OutputStream out) {
Thread t = new Thread(new Runnable() {
public void run() {
try {
int d;
while ((d = inputStream.read()) != -1) {
out.write(d);
}
} catch (IOException ex) {
//TODO make a callback on exception.
}
}
});
t.setDaemon(true);
t.start();
}
{
Process p = ...;
inputStreamToOutputStream(p.getErrorStream(), System.out);
inputStreamToOutputStream(p.getInputStream(), System.out);
}
从中可以帮助您:
String output = new VerboseProcess(new ProcessBuilder("foo.bat")).stdout();
如果您希望使用更多Groovy和更少java来实现这一点,那么这将按实际情况打印每一行:
def cmd = "./longRunningProcess"
def process = cmd.execute()
process.in.eachLine { line -> println line }
或者,如果您想同时看到stdout和stderr
def cmd = "./longRunningProcess"
def process = cmd.execute()
process.waitForProcessOutput( System.out, System.err )
使用inheritIO()方法将所有流重定向到标准输出很简单。这会将输出打印到运行此命令的进程的标准输出
ProcessBuilder pb = new ProcessBuilder("command", "argument");
pb.directory(new File(<directory from where you want to run the command>));
pb.inheritIO();
Process p = pb.start();
p.waitFor();
我认为这只会在流程完成后打印所有输出。我希望在生成输出后立即查看输出。如果foo.bat的输出对于stdout缓冲区来说“太大”,那么这将停止foo.bat的执行。与我的问题类似,如果进程目前没有输出内容,循环将在进程完成之前结束,对吗?while循环将等待下一行输入。这是正确回答问题的答案。OP询问如何重定向输出,而不是如何打印输出的每一行。非常重要的区别我无法充分肯定这一点,你帮了我很多忙。
pb.redirectInput(Redirect.INHERIT)
pb.redirectOutput(Redirect.INHERIT)
pb.redirectError(Redirect.INHERIT)