2016-10-22 1 views
2

Ich möchte einen Prozess für einige Zeit ausführen und dann die Ausgabe abrufen und den Prozess zu zerstören. Dies ist mein CodeHolen Sie das Ausgabeergebnis eines Prozesses mit 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()); 

aber ich als Ergebnis erhalten

java.io.IOException: Stream closed 

Wie kann ich das Ergebnis nach Ausführung des Prozesses 7 Sekunden kopieren? Wenn ich diesen Code verwenden

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

die while-Schleife endet nie, weil der Prozess noch am Leben nach dem waitFor ist, also muss ich es zerstören. Und wenn ich den Prozess zerstöre, kann ich den Inhalt von stdInput nicht mehr bekommen.

Antwort

2

Sie wollen diesen Aufruf nicht an waitFor(), da es wartet, bis der Prozess zerstört wird. Sie möchten auch nicht so lange lesen, wie der InpuutStream geöffnet ist, da ein solcher Lesevorgang nur beendet würde, wenn der Prozess beendet wird.

Stattdessen können Sie einfach den Prozess starten und warten Sie dann 7 Sekunden. Nach 7 Sekunden vergangen sind, lesen Sie die verfügbaren Daten im Puffer für den Strom, ohne zu warten, um zu schließen:

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. 

Wenn der Prozess Druck hält, so stdInput.ready() immer true zurück, Sie so etwas wie dies versuchen:

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 

In dieser Lösung, statt zu schlafen, verbringt der Thread die nächsten 7 Sekunden lesen von InputStream, dann schließt es den Prozess.

+0

readLine() ist nicht genug? Sie denken, dass ready() möglicherweise false zurückgibt, wenn readLine() true zurückgibt? – davidxxx

+0

Die while-Schleife wird niemals beendet, da immer etwas im Puffer zu lesen ist, bis der Prozess stoppt – sonia

+0

'p.waitFor (7, TimeUnit.SECONDS);' blockiert den Thread für '7' Sekunden oder bis der Prozess endet Dieser Aufruf muss nicht durch 'Thread.sleep (7000);' ersetzt werden. – Titus

0

java.io.IOException: Stream closed Das ist wahrscheinlich, weil Sie temp.readLine() nach p.destroy() aufrufen.

Das Problem scheint zu sein, dass der Prozess nach dem Teil, den Sie abrufen möchten, keinen neuen Zeilenabschluss hinzufügt. Um das zu beheben, können Sie die Ausgabe aus dem Programm in kleinen Blöcken statt Zeile für Zeile lesen. Hier

ein Beispiel:

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(); 
} 

Wenn Sie das genaue Format des Programms der Ausgabe wissen, eine bessere Lösung besteht darin, einen Scanner zu verwenden.

Das obige Beispiel liest die Ausgabe des Programms Wort für Wort.

Aus Ihren Kommentaren scheint, dass das Problem ist, dass der Prozess nie von selbst beendet und Ihr Programm nie die while Schleife verlässt.

Um das zu beheben, können Sie einen Timer verwenden können, um den Prozess nach einer gewissen Zeit zu zerstören, ist hier ein Beispiel:

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(); 
} 

Beachten Sie, dass dieser Ansatz immer stdInput.readLine() verursachen eine Ausnahme zu werfen.

+0

Das Problem ist nicht die Newline, es ist die Tatsache, dass er den 'InputStream' liest, solange es offen ist, bis der Prozess beendet ist. Vielleicht weiß er auch nicht, was "alles" ist.OP versucht nur, den während dieser 7 Sekunden ausgedruckten Prozess zu lesen. – Malt

+0

Ich habe Ihren Code ausprobiert, er wird nie beendet, wenn der Prozess keine Ausgabe zurückgibt. Es gibt auch java.io.IOException zurück: Stream geschlossen, wenn der Prozess eine Ausgabe zurückgibt – sonia

Verwandte Themen