2015-12-20 2 views
2

В моем приложении Java мне нужно выполнить некоторые сценарии в качестве подпроцессов и контролировать вывод на stdout из Java, чтобы я мог реагировать, когда это необходимо, на некоторый вывод.Чтение потока stdout из подпроцесса по мере его появления

Я использую apache commons-exec для создания подпроцесса и перенаправления stdout исполняемого скрипта на входной поток.

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

Ниже мой Java-код:

public class SubProcessReact { 
    public static class LogOutputStreamImpl extends LogOutputStream { 

     @Override 
     protected void processLine(String line, int logLevel) { 
      System.out.println("R: " + line); 
     } 
    } 

    public static void main (String[] args) throws IOException, InterruptedException { 
     CommandLine cl = CommandLine.parse("python printNumbers.py"); 
     DefaultExecutor e = new DefaultExecutor(); 
     ExecuteStreamHandler sh = new PumpStreamHandler(new LogOutputStreamImpl()); 
     e.setStreamHandler(sh); 

     Thread th = new Thread(() -> { 
      try { 
       e.execute(cl); 
      } catch (IOException e1) { 
       e1.printStackTrace(); 
      } 
     }); 

     th.start(); 
    } 
} 

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

Python код:.

import time 

for x in range(0,10): 
    print x 
    time.sleep(1) 

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

Есть ли что-то, что я мог бы сделать, чтобы сделать эту работу так, как я намерен?

ответ

1

Зачем использовать стороннюю библиотеку для выполнения чего-то Java SE уже хорошо? Лично я предпочитаю зависеть, как несколько внешних библиотек, как это возможно, для того, чтобы мои программы легко переносимыми и сократить точки отказа:

ProcessBuilder builder = new ProcessBuilder("python", "printNumbers.py"); 
builder.inheritIO().redirectOutput(ProcessBuilder.Redirect.PIPE); 
Process process = builder.start(); 

try (BufferedReader reader = new BufferedReader(
    new InputStreamReader(process.getInputStream()))) { 

    reader.lines().forEach(line -> System.out.println("R: " + line)); 
} 

process.waitFor(); 
+0

Спасибо за ваш ответ, но это не решает мою проблему. Мне нужно уметь читать каждую строку, когда она входит в поток. С этим решением у меня та же проблема, что и в моем исходном коде, я могу получить весь результат после завершения завершения скрипта. Мне нужно уметь читать каждую строку по мере ее появления. – apatrick

+2

@apatrick: кроме того, чтобы читать одну строку за раз в вашем Java-коде, вам может понадобиться флаг '-u', чтобы отключить буферизацию' python' ' s stdout/stderr. В противном случае, при перенаправлении вывод блокируется блоком. См. [Мой ответ на аналогичный вопрос, но для 'Python'] (http://stackoverflow.com/a/17698359/4279) – jfs

+0

@ J.F.Sebastian Это решило мою проблему. Я не думал, что проблема будет на стороне Python. Большое вам спасибо! – apatrick