2013-07-15 2 views
0

Я написал эту простую TestCase, который описывает меня проблема:Java подпроцесс не записывает выходные данные, пока он не закончит

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

То, что я получаю, это то, что вывод подпроцесса полностью записан, когда он завершается. Вот результат:

Mon Jul 15 19:17:13 CEST 2013: starting process 
Mon Jul 15 19:17:14 CEST 2013: process started 
Mon Jul 15 19:17:14 CEST 2013: waiting for process termination 
Mon Jul 15 19:17:14 CEST 2013: readerThread is starting 
Mon Jul 15 19:17:19 CEST 2013: process terminated correctly 
Mon Jul 15 19:17:19 CEST 2013: Thread[Thread-0,5,main] got line: foo(7) 
Mon Jul 15 19:17:19 CEST 2013: Thread[Thread-0,5,main] got line: foo(49) 
Mon Jul 15 19:17:19 CEST 2013: Thread[Thread-0,5,main] got line: foo(73) 
Mon Jul 15 19:17:19 CEST 2013: Thread[Thread-0,5,main] got line: foo(58) 
Mon Jul 15 19:17:19 CEST 2013: Thread[Thread-0,5,main] got line: foo(30) 
Mon Jul 15 19:17:19 CEST 2013: readerThread is terminating 

с этим кодом:

public class MiniTest { 
    static void println(String x) { 
     System.out.println(new Date() + ": " + x); 
    } 

    public static void main(String[] args) throws IOException, InterruptedException { 
     ProcessBuilder pb = new ProcessBuilder("bin/dummy", "foo", "5"); 

     println("starting process"); 
     Process p = pb.start(); 
     println("process started"); 

     new ReaderThread(p).start(); 

     println("waiting for process termination"); 
     p.waitFor(); 
     println("process terminated correctly"); 
    } 

    static class ReaderThread extends Thread { 
     private Process p; 

     public ReaderThread(Process p) { 
      this.p = p; 
     } 

     public void run() { 
      println("readerThread is starting"); 
      BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream())); 
      String line; 
      try { 
       while((line = r.readLine()) != null) { 
        println(this + " got line: " + line); 
       } 
      } catch(IOException e) { 
       println("read error: " + e); 
      } 
      println("readerThread is terminating"); 
     } 
    } 
} 

Примечание: подпроцесс очень прост, он выводит строку каждую секунду, в течение определенного abount итераций (и при испытании на командной строки, это так):

#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char **argv) { 
    char *f = argv[1]; 
    int n = atoi(argv[2]); 
    while(n-- > 0) { 
     printf("%s(%d)\n", f, rand() % 100); 
     sleep(1); 
    } 
    return 0; 
} 
+2

Вы называете 'вровень()' после каждой строки принимается? – mattbdean

+0

@whowantsakookie Вы могли бы быть более конкретным? назовите флеш на что? Кстати, «после того, как каждая строка получена» не работает, я получаю все строки одним выстрелом в конце – fferri

+0

@whowantsakookie Я попытался добавить fflush (stdout) после printf, и он работает :), но как я могу решить это в Генеральная? возможно ли сделать неявное промывание в InputStream, как и терминал (я полагаю)? – fferri

ответ

0

Нашел ответ, спросив и изучив вопрос.

Проблема не может быть легко решена, но, по-видимому, это проблема с libc. Если на выходе это не tty/pty, буферизация не по строке.

Существуют внешние программы или скрипты, которые позволяют обойти это, например, stdbuf или unbuffer (from expect).

Подробное описание: Force line-buffering of stdout when piping to tee