2016-10-22 6 views
2

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

BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream())); 
BufferedReader temp; 
p.waitFor(7, TimeUnit.SECONDS); 
temp=stdInput; 
p.destroy(); 
System.out.println(temp.readLine()); 

, но я получаю в результате

java.io.IOException: Stream closed 

Как скопировать результат после выполнения процесса 7 секунд? Если я использую этот код

p.waitFor(7, TimeUnit.SECONDS); 
while ((inputRead=stdInput.readLine()) != null){ 
    Helper.log(inputRead); 
} 

цикл в то время как никогда не прекращается, потому что этот процесс все еще жив после waitFor, так что я должен уничтожить его. И если я уничтожу процесс, я больше не смогу получить содержимое stdInput.

ответ

2

Вы не хотите, чтобы этот вызов вызывал waitFor(), так как он ждет, пока процесс не будет уничтожен. Вы также не хотите читать до тех пор, пока InpuutStream открыт, поскольку такое чтение прекращается только тогда, когда процесс будет убит.

Вместо этого вы можете просто запустить процесс, а затем подождать 7 секунд. После того, как прошло 7 секунд, прочитать имеющиеся данные в буфер, не дожидаясь потока, чтобы закрыть:

BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream())); 
Thread.sleep(7000); //Sleep for 7 seconds 
while (stdInput.ready()) { //While there's something in the buffer 
    //read&print - replace with a buffered read (into an array) if the output doesn't contain CR/LF 
    System.out.println(stdInput.readLine()); 
} 
p.destroy(); //The buffer is now empty, kill the process. 

Если процесс будет продолжать печатать, так stdInput.ready() всегда возвращает истину, вы можете попробовать что-то вроде этого:

BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream())); 
char[] buffer = new char[16 * 1024]; // 16 KiB buffer, change size if needed 
long startedReadingAt = System.currentTimeMillis(); //When did we start reading? 
while (System.currentTimeMillis() - startedReadingAt < 7000) { //While we're waiting 
    if (stdInput.ready()){ 
     int charsRead = stdInput.read(buffer); //read into the buffer - don't use readLine() so we don't wait for a CR/LF 
     System.out.println(new String(buffer, 0, charsRead)); //print the content we've read 
    } else { 
     Thread.sleep(100); // Wait for a while before we try again 
    } 
} 
p.destroy(); //Kill the process 

В этом решении вместо сна поток проводит следующие 7 секунд чтения с InputStream, затем он закрывает процесс.

+0

readLine() недостаточно? Вы думаете, что ready() может возвращать false, когда readLine() возвращает true? – davidxxx

+0

цикл while никогда не будет завершен, потому что всегда будет что-то читать в буфере, пока процесс не остановится – sonia

+0

'p.waitFor (7, TimeUnit.SECONDS);' блокирует поток для '7' секунд или до тех пор, пока процесс не завершится так нет необходимости заменять этот вызов 'Thread.sleep (7000);'. – Titus

0

java.io.IOException: Stream closed Возможно, это потому, что вы звоните temp.readLine() после p.destroy().

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

Вот пример:

try(InputStream is = p.getInputStream()){ 
    byte[] buffer = new byte[10]; 
    String content = ""; 
    for(int r = 0; (r = is.read(buffer))!=-1;){ 
     content+=new String(buffer, 0, r); 
     if(content.equals("all content")){// check if all the necessary data was retrieved. 
      p.destroy(); 
      break; 
     } 
    } 
}catch(Exception e){ 
    e.printStackTrace(); 
} 

Если вы знаете точный формат вывода программы, лучшим решением будет использовать сканер.

try(Scanner sc = new Scanner(p.getInputStream())){ 
    while(sc.hasNext()){ 
     String word = sc.next(); 
    } 
}catch(Exception e){ 
    e.printStackTrace(); 
} 

В приведенном выше примере будет отображаться выход программы по одному слову за раз.

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

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

Timer t = new Timer(); 
t.schedule(new TimerTask() { 
    @Override 
    public void run() { 
     p.destroy(); 
     t.cancel(); 
     t.purge(); 
    } 
}, 7000); 

try(BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));){ 
    while ((inputRead=stdInput.readLine()) != null){ 
     ... 
    } 
}catch(Exception e){ 
    e.printStackTrace(); 
} 

Имейте в виду, что этот подход всегда будет вызывать stdInput.readLine() бросить исключение.

+0

Проблема не в новой строке, это факт, что он читает 'InputStream' до тех пор, пока он открыт, пока процесс не будет убит. Кроме того, он может не знать, что такое «весь контент».OP просто пытается прочитать любой процесс, распечатанный за эти 7 секунд. – Malt

+0

Я пробовал свой код, он никогда не заканчивается, если процесс не возвращает никакого вывода. Он также возвращает java.io.IOException: поток закрыт, если процесс возвращает некоторый вывод – sonia

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