java 获取进程的输出结果
Get the output result of a process with 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);
}
while 循环永远不会终止,因为在 waitFor
之后进程仍然存在,所以我必须销毁它。如果我破坏了进程,我将无法再获取 stdInput
的内容。
java.io.IOException: Stream closed
这可能是因为您在 p.destroy()
之后调用 temp.readLine()
。
问题似乎是进程没有在您要检索的部分之后添加新的行终止符。要解决此问题,您可以分块读取程序的输出,而不是逐行读取。
这是一个例子:
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()
抛出异常。
您不希望调用 waitFor()
,因为它会一直等到进程被销毁。只要 InputStream
打开,您也不想读取,因为这样的读取只有在进程被终止时才会终止。
相反,您可以简单地启动进程,然后等待 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()
总是 returns 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
在此解决方案中,线程没有休眠,而是在接下来的 7 秒内从 InputStream
读取数据,然后关闭进程。
我想执行一个进程一段时间,然后获取输出并销毁该进程。这是我的代码
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);
}
while 循环永远不会终止,因为在 waitFor
之后进程仍然存在,所以我必须销毁它。如果我破坏了进程,我将无法再获取 stdInput
的内容。
java.io.IOException: Stream closed
这可能是因为您在 p.destroy()
之后调用 temp.readLine()
。
问题似乎是进程没有在您要检索的部分之后添加新的行终止符。要解决此问题,您可以分块读取程序的输出,而不是逐行读取。
这是一个例子:
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()
抛出异常。
您不希望调用 waitFor()
,因为它会一直等到进程被销毁。只要 InputStream
打开,您也不想读取,因为这样的读取只有在进程被终止时才会终止。
相反,您可以简单地启动进程,然后等待 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()
总是 returns 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
在此解决方案中,线程没有休眠,而是在接下来的 7 秒内从 InputStream
读取数据,然后关闭进程。