Перенаправить вывод процесса на стандартный вывод - PullRequest
24 голосов
/ 14 ноября 2009

Я хотел бы запустить foo.bat из программы Groovy и перенаправить вывод полученного процесса на стандартный вывод. Пример кода на Java или Groovy будет в порядке.

foo.bat может занять несколько минут и генерировать много выходных данных, поэтому я хотел бы видеть выходные данные, как только они будут созданы, вместо того, чтобы ждать, пока процесс завершится, прежде чем увидеть все выходные один раз.

Ответы [ 7 ]

51 голосов
/ 29 апреля 2014

Просто перенаправить весь ваш поток на стандартный вывод, используя метод attributeit (). Это выведет вывод на стандартный вывод процесса, из которого вы запускаете эту команду.

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)
33 голосов
/ 14 ноября 2009

Используется класс, который читает все выходные данные, которые генерирует исполняемая программа, и отображает их в своем собственном стандартном выводе.

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();
7 голосов
/ 29 января 2014

Если вы хотите сделать это с большим количеством 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 )
4 голосов
/ 14 ноября 2009

Следующий код Groovy выполнит foo.bat и отправит вывод на стандартный вывод:

println "foo.bat".execute().text
4 голосов
/ 14 ноября 2009

Вот что-то немного проще, если вы просто пытаетесь получить вывод простой команды. Вам нужно будет использовать потоки, как это делает джиттер, если вы хотите обрабатывать параллельно, или если ваша команда принимает стандартный ввод или генерирует стандартный вывод.

Используйте буферизованную копию (например, 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();
  }
}
2 голосов
/ 28 июня 2012

Асинхронный способ достижения этого.

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);
}
0 голосов
/ 02 января 2013

VerboseProcess из jcabi-log может помочь вам:

String output = new VerboseProcess(new ProcessBuilder("foo.bat")).stdout();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...