简体   繁体   English

使用java获取进程的输出结果

[英]Get the output result of a process with java

I want to execute a process for some time and then get the output and destroy the process. 我想执行一段时间的进程,然后获取输出并销毁进程。 This is my code 这是我的代码

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

but I get as result 但我得到了结果

java.io.IOException: Stream closed

How can I copy the result after executing the process 7 seconds? 如何在执行过程7秒后复制结果? If I use this code 如果我使用此代码

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

the while loop will never terminate because the process is still alive after the waitFor , so I have to destroy it. while循环永远不会终止,因为进程在waitFor之后仍然存在,所以我必须销毁它。 And If I destroy the process I am not able to get the content of stdInput anymore. 如果我破坏了这个过程,我就不能再获得stdInput的内容了。

You don't want that call to waitFor() since it waits until the process is destroyed. 你不希望调用waitFor()因为它等待进程被销毁。 You also don't want to read for as long as the InpuutStream is open, since such a read would terminate only when the process is killed. 只要InpuutStream处于打开状态,您也不想阅读,因为只有在进程被终止时才会终止此类读取。

Instead, you can simply start the process, and then wait for 7 seconds. 相反,您可以简单地启动该过程,然后等待7秒钟。 Once 7 seconds have passed, read the available data in the buffer without waiting for the stream to close: 一旦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.

If the process keeps printing, so stdInput.ready() always returns true you can try something like this: 如果进程继续打印,那么stdInput.ready()总是返回true,你可以尝试这样的事情:

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 this solution, instead of sleeping, the thread spends the next 7 seconds reading from the InputStream , then it closes the process. 在这个解决方案中,线程不是休眠,而是从InputStream读取接下来的7秒,然后关闭进程。

java.io.IOException: Stream closed That is probably because you're calling temp.readLine() after p.destroy() . java.io.IOException: Stream closed这可能是因为你在temp.readLine()之后调用了p.destroy()

The problem seems to be that the process doesn't add a new line termination after the part that you want to retrieve. 问题似乎是该进程不会在您要检索的部分之后添加新的行终止。 To fix that, you can read the output from the program in small chunks instead of line by line. 要解决这个问题,您可以用小块而不是逐行读取程序的输出。

Here is an example: 这是一个例子:

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

If you know the exact format of the program's output, a better solution will be to use a scanner. 如果您知道程序输出的确切格式,更好的解决方案是使用扫描仪。

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

The example above will read the program's output one word at a time. 上面的例子将一次读取程序的输出一个字。

From your comments it seems that the problem is that the process never terminates by itself and your program never exits the while loop. 从您的评论看来,问题是该过程永远不会自行终止,您的程序永远不会退出while循环。

To fix that, you can use a timer to destroy the process after a period of time, here is an example: 要解决这个问题,您可以使用计时器在一段时间后销毁进程,这是一个示例:

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

Keep in mind that this approach will always cause stdInput.readLine() to throw an exception. 请记住,此方法将始终导致stdInput.readLine()抛出异常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM