2017-02-20 2 views
0

У меня есть .jar файл, который держит в ожидании ввода пользователя, процесса и распечатки результатов (в несколько строк), как этотВ Java BufferedReader Readline блоки на интерактивной оболочки

>Input sentence 1 
Result 1 
Result 2 
>Input sentence 2 
Result 1 
Result 2 
Result 3 
> 

Единственный способ выйти из этого банку программа нажатием Ctrl + C.

Теперь я хочу вызвать этот файл jar из моей java-программы. Мой код выглядит следующим образом:

processBuilder = new ProcessBuilder(PATH_TO_BIN); 
Process process = processBuilder.start(); 
writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream())); 
reader = new BufferedReader(new InputStreamReader(process.getInputStream())); 

writer.write(inputSentence); 
writer.newLine(); 
writer.flush(); 
String line; 
while ((line = reader.readLine()) != null){ //<<<< it hangs here 
    System.out.println(line); 
} 

Моя программа может успешно распечатать результат, возвращаемый программой «баночки», но держать висит на следующей reader.readLine() и я не могу предоставить следующий вход в программу «банку».

Есть ли способ исправить эту проблему?

Заранее благодарен!

+0

Вы не пишете ничего на банку в вашем 'while' цикла. Он ждет ввода, и вы ждете его выхода. Добавьте некоторую 'запись' после' System.out.println – AhmadWabbi

+0

@AhmadWabbi, может быть, я не очень четко сказал в своем вопросе, но файл JAR может давать несколько строк результатов, а не только одну строку, поэтому мне нужно читать все строки результата, используя цикл while, как вы можете видеть –

+0

В вашем примере это было даже не ясно. В этом случае невозможно провести различие между вашей программой, ожидающей следующего результата, и ждать навсегда, потому что банка закончила выдавать результаты и ждет Ctrl- C. Даже «peek» не будет различать. Я не вижу решения, кроме отправки Ctrl-C, используя поток после достаточного таймаута. – AhmadWabbi

ответ

0

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

ProcessBuilder processBuilder = new ProcessBuilder(PATH_TO_BIN); 
    Process process = processBuilder.start(); 
    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream())); 


    new Thread { 
     public void run() { 
     BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); 
     String line = null; 
     do {    
      line = reader.readLine(); 
      System.out.println(line); 
     } while (line != null){ //<<<< it waits here for next line of input 
     } 
    }.start(); 


    // and here you can write something to the process InputSteram... 
    writer.write(inputSentence); 
    writer.newLine(); 
    writer.flush(); 
+0

Приносим извинения за недостаточное уточнение, результат может иметь несколько строк, а не только одну строку, как в моем первоначальном примере. Я обновил свой вопрос. –

+0

Он не «ждет здесь следующей строки ввода», где «здесь» является условием «делать/в то время». Он ждет 'readLine()'. – EJP

+0

любезно объяснить downvote? –

0

Метод готов() из BufferedReader -Tells готов ли быть этот поток читать.

Вы можете использовать этот метод, чтобы проверить, если поток готов для чтения, и если да, вы можете сделать свою работу,

while (reader.ready()){ 
//Do the processing 
} 

Смотрите, если это работает.

+0

Я попытался использовать этот метод 'ready', но он вернул' false' и не попал в тело цикла while. –

+0

Это не помешает 'readLine()' от блокировки, если терминатор линии не был отправлен. – EJP

0

Я собираюсь использовать ответ @ Krzystof, однако я предполагаю, что вы собираетесь использовать Java 7 или 8 (+).

В этом случае, вы должны использовать Try-С-ресурсов, а именно:

public static void main (String[] args) throws java.lang.Exception { 

    ProcessBuilder prBuilder = new ProcessBuilder("/path/to/bin"); 
    Process process = prBuilder.start(); 
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())) | BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()))) { 

     String line; 

     while ((line = reader.readLine()) != null) { 
      // Process input 
     } 

    } catch (IOException ex) { 
     // Process IOException 
    } finally { 
     process.kill(); 
    } 
} 
+0

Спасибо, что поделились этим. Однако этот код все еще висит на 'line = reader.readLine()', правильно? Я также обновил свой вопрос для получения дополнительной информации. –

+0

Вы можете использовать следующие условия: 'while (reader.peek()! = -1)' Я уверен в точном поведении, но я не знаю, что он «висит». В любом случае, хорошо, что приложение ожидает следующего ввода. В противном случае вы будете передавать, возможно, неполные данные. По какой причине у вас есть необходимость в непрерывном вводе/выводе? – SimonC

+1

Я не вижу 'peek()' метод в объекте BufferedReader, возможно, это для Java 6. Я использую Java 8. JAR-файл предоставляется сторонним разработчиком, я не контролирую его. Я хочу попросить пользователя предоставить вход, передать его в JAR-программу и получить выход. JAR-файл должен инициализировать кучу моделей каждый раз, когда он запускается. –