我想從Groovy程序中執行foo.bat,並將生成的過程輸出重定向到標準輸出。 Java或Groovy代碼示例都可以。將過程輸出重定向到標準輸出
foo.bat可能需要幾分鐘的時間才能運行並生成大量的輸出,所以我希望在生成它時立即看到輸出,而不必等到處理完成才能看到所有輸出立刻。
我想從Groovy程序中執行foo.bat,並將生成的過程輸出重定向到標準輸出。 Java或Groovy代碼示例都可以。將過程輸出重定向到標準輸出
foo.bat可能需要幾分鐘的時間才能運行並生成大量的輸出,所以我希望在生成它時立即看到輸出,而不必等到處理完成才能看到所有輸出立刻。
它使用一個讀取所有輸出執行的程序生成的類,並將其顯示在它自己的stdout中。
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();
我的問題是,如果過程沒有在此刻輸出什麼東東,循環將在過程結束之前結束,對吧? – 2015-09-03 10:41:19
while循環將一直等到下一行輸入。 – Crummy 2016-07-28 13:49:31
如果你只是想抓住一個簡單命令的輸出,這裏有點簡單。如果要並行處理或者命令使用stdin或生成stderr,則需要使用像jitter一樣的線程。
如果您獲得大量輸出,請使用緩衝副本(如this)。
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和輸出發送到標準輸出:
println "foo.bat".execute().text
我認爲這將只在打印完成後打印所有輸出。我想在生成後立即看到輸出 – 2009-11-16 15:15:57
另外,如果foo.bat的輸出對於標準輸出緩衝區「太大」,這將停止執行foo.bat。 – billjamesdev 2013-11-08 02:11:21
異步的方式來實現它。
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);
}
VerboseProcess
從jcabi-log可以幫助你:
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()方法將所有流重定向到標準輸出很簡單。這會將輸出打印到正在運行此命令的進程的stdout。
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();
也存在其他方法,如下所述。這些單獨的方法將幫助僅重定向所需的流。
pb.redirectInput(Redirect.INHERIT)
pb.redirectOutput(Redirect.INHERIT)
pb.redirectError(Redirect.INHERIT)
這是正確回答問題的答案。 OP詢問如何重定向輸出,而不是如何打印輸出的每一行。非常重要的區別 – Brandon 2016-12-10 01:19:19
我不能滿足這一點,你已經幫了我很多。 – 2017-11-23 11:31:06
類似http://stackoverflow.com/questions/1670798/using-a-thread-to-capture-process-output – yegor256 2013-01-02 15:44:25