Java 将进程输出重定向到标准输出

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1732455/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 22:00:38  来源:igfitidea点击:

Redirect process output to stdout

javagroovy

提问by Dónal

I would like to execute foo.bat from within a Groovy program and have the resulting process' output redirected to stdout. Either a Java or Groovy code example would be fine.

我想从 Groovy 程序中执行 foo.bat 并将结果进程的输出重定向到 stdout。Java 或 Groovy 代码示例都可以。

foo.bat can take several minutes to run and generates a lot of output, so I would like to see the output as soon as it is generated, rather than having to wait until the process has completed before seeing all the output at once.

foo.bat 可能需要几分钟才能运行并生成大量输出,因此我希望在生成后立即查看输出,而不必等到进程完成才能立即查看所有输出。

采纳答案by jitter

This uses a class which reads all output the executed program generates and displays it in it's own 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();

回答by Keith Randall

Here's something a little simpler if you're just trying to grab the output of a simple command. You'll need to use threads like jitter does if you want to process in parallel or if your command takes stdin or generates stderr.

如果您只是想获取一个简单命令的输出,这里有一些更简单的东西。如果您想并行处理或者如果您的命令采用 stdin 或生成 std​​err,则需要像 jitter 那样使用线程。

Use a buffered copy (like this) if you're getting lots of output.

如果您获得大量输出,请使用缓冲副本(像这样)。

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();
  }
}

回答by John Wagenleitner

The following Groovy code will execute foo.bat and send the output to stdout:

以下 Groovy 代码将执行 foo.bat 并将输出发送到 stdout:

println "foo.bat".execute().text

回答by Daniel De León

Asynchronous way to achieve it.

异步方式来实现它。

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);
}

回答by yegor256

VerboseProcessfrom jcabi-logcan help you:

VerboseProcess来自jcabi-log可以帮助您:

String output = new VerboseProcess(new ProcessBuilder("foo.bat")).stdout();

回答by gMale

If you're looking to do this with more Groovy and less java, this will print each line as it happens:

如果你想用更多的 Groovy 和更少的 java 来做到这一点,这将在发生时打印每一行:

def cmd = "./longRunningProcess"

def process = cmd.execute()
process.in.eachLine { line -> println line }

Alternatively, if you want to see both stdout and stderr

或者,如果您想同时查看 stdout 和 stderr

def cmd = "./longRunningProcess"

def process = cmd.execute()
process.waitForProcessOutput( System.out, System.err )

回答by Pandurang Patil

It is simple to redirect all your stream to standard output using inheritIO() method. This will print the output to the stdout of the process from which you are running this command.

使用 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();

There exist other methods too, like as mentioned below. These individual methods will help redirect only required stream.

还有其他方法,如下所述。这些单独的方法将有助于仅重定向所需的流。

    pb.redirectInput(Redirect.INHERIT)
    pb.redirectOutput(Redirect.INHERIT)
    pb.redirectError(Redirect.INHERIT)