2015-11-16 2 views
2

Я пишу программу для чтения команд из файла, их выполнения и печати результата каждой команды.Обработчик обработки ProcessBuilder

Это то, что у меня есть: import java.io. *;

public class StatsGenerator { 
    public static void main(String [] args) throws IOException { 
     ProcessBuilder builder = new ProcessBuilder("/bin/bash"); 
     Process p = builder.start(); 

     // get output from the process 
     InputStream is = p.getInputStream(); 
     InputStreamReader isr = new InputStreamReader(is); 
     BufferedReader processOutput = new BufferedReader(isr); 

     InputStream errorStream = p.getErrorStream(); 
     InputStreamReader inputStreamReader = new InputStreamReader(errorStream); 
     BufferedReader processErrorOutput = new BufferedReader(inputStreamReader); 

     // get input to the process 
     BufferedWriter processInput = new BufferedWriter(new OutputStreamWriter(p.getOutputStream())); 

     // get commands to execute 
     File f = new File("commands.txt"); 
     FileReader fileReader = new FileReader(f); 
     BufferedReader commandsReader = new BufferedReader(fileReader); 
     String command, output; 
     while((command = commandsReader.readLine()) != null) { 
      System.out.printf("Output of running %s is:\n", command); 
      processInput.write(command); 
      processInput.newLine(); 
      processInput.flush(); 
      while (processErrorOutput.ready() && (output = processErrorOutput.readLine()) != null) { 
       System.out.println(output); 
      } 
      while ((output = processOutput.readLine()) != null) { 
       System.out.println(output); 
      } 
     } 

     // close process 
     processInput.write("exit"); 
     processInput.newLine(); 
     processInput.flush(); 

     // close streams 
     commandsReader.close(); 
     processErrorOutput.close(); 
     processInput.close(); 
     processOutput.close(); 

    } 
} 

Commands.txt

java Solve problems/problem01.txt 
java Solve problems/problem02.txt 
java Solve problems/problem03.txt 

Однако это работает и выводит результат первой команды, но застревает на втором ... (и я знаю, что решить можно решить вторую)

enter image description here

Что я делаю неправильно?

EDIT1:

Оказывается, «Исключение в потоке" основной»ошибка из картины из-за меня, нажав CMD + C. Это все еще не объясняет, почему он перестает выводить.

+0

Почему вы используете командный интерпретатор, чтобы начать? – fge

ответ

1

Проблема, которую я вижу здесь, заключается в том, что вы создаете процесс, запускающий оболочку (ОК), получите входные и выходные потоки этого процесса (ОК), прочитайте команду из файла (OK) и подайте ее на процесс (ОК). Затем вы продолжаете читать выходные строки, которые успешно выполняются, пока первая программа Java выполняет и производит вывод.

Тогда

while ((output = processOutput.readLine()) != null) { ... 

блоки, как не существует ни одна линия, ни EOF.

Вы можете исправить это, создав поток для чтения и печати processOutput.

Другой вариант (который я бы предпочел) - создать один процесс для каждой команды. Насколько я вижу, вам даже не нужна оболочка: вы можете сразу выполнить java SolveProblem .... (Unices были созданы для эффективного создания подпроцесса и не думают, что оболочка делает это по-другому, поэтому нет никаких дополнительных накладных расходов, которых можно бояться.)

Всего два подсказки для вызова java без оболочки: не забудьте использовать полное имя пути и разделение командной строки на токены.

Редактировать И вот он, просто используя String [] вместо текстового файла, содержащего команды.

for(String cmd: new String[]{ "java Y aaa", "java Y bbb","java Y ccc" }){ 
    String[] toks = cmd.split("\\s"); 
    ProcessBuilder builder = new ProcessBuilder(toks); 
    Process p = builder.start(); 

    // get output from the process 
    InputStream is = p.getInputStream(); 
    InputStreamReader isr = new InputStreamReader(is); 
    BufferedReader processOutput = new BufferedReader(isr); 

    InputStream errorStream = p.getErrorStream(); 
    InputStreamReader inputStreamReader = new InputStreamReader(errorStream); 
    BufferedReader processErrorOutput = new BufferedReader(inputStreamReader); 
    System.out.println("Executing " + cmd); 
    String output; 
    while(processErrorOutput.ready() && 
     (output = processErrorOutput.readLine()) != null) { 
    System.out.println(output); 
    } 
    while ((output = processOutput.readLine()) != null) { 
    System.out.println(output); 
    } 
    processErrorOutput.close(); 
    processOutput.close(); 
} 

Выхода (глупо Y печатает аргумент в три раза):

 
Executing java Y aaa 
1aaa 
2aaa 
3aaa 
Executing java Y bbb 
1bbb 
2bbb 
3bbb 
Executing java Y ccc 
1ccc 
2ccc 
3ccc 

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

processInput.write(command + "; echo xxxEOFxxx"); 
//... 
while ((output = processOutput.readLine()) != null 
     && ! "xxxEOFxxx".equals(output)) { 
    System.out.println(output); 
} 

Altho Мне не нравится использование «магических строк» ​​таким образом, что здесь может быть допустимо, поскольку вы знаете набор выходных строк программы Solve.

+0

"прочитайте команду из файла (ОК)" <- uh? Учитывая вызов bash, он не сможет интерпретировать этот командный файл по меньшей мере .... – fge

+0

То, как я себе представлял, это то, что я открываю bash, выполняю первую команду, читаю ее вывод, выполняю вторую (0 = 0) блоков Я ожидал, что он продолжит работу после того, как процесс заполнит процесс. с новым выходом. Причина, по которой я делаю это, - это то, что мне нужны выходы каждой команды в одном месте после этого. – mp3por

+0

Я знаю, что вы имели в виду, но программа Java не ощущает конца вывода первого вызова программы. - То, что я предложил, все равно позволит вам обрабатывать выходные данные любым способом. Еще лучше, потому что с отдельными процессами вы будете * иметь EOF после каждого исполнения. – laune

0

А еще лучше, чтобы запустить ошибку и чтение потока в отдельных потоках, для того, чтобы обеспечить грим программу, способную сделать что-то другое, прекратить процесс, например

Смежные вопросы