【发布时间】:2012-10-31 14:46:54
【问题描述】:
我希望能够从 Java 生成一个外部进程,并定期写入其输入并读取响应,就好像它是控制台一样。然而,很多时候,当我阅读进程的输出时,什么都没有。有没有做这种事情的好习惯(甚至避免它)?
下面是一个关于什么不起作用的精简示例:
import org.apache.commons.exec.*;
import java.io.*;
//...
CommandLine cl = CommandLine.parse("/usr/bin/awk {print($1-1)}");
System.out.println(cl.toStrings());
Process proc = new ProcessBuilder(cl.toStrings()).start();
OutputStream os = proc.getOutputStream(); // avoiding *Buffered* classes
InputStream is = proc.getInputStream(); // to lessen buffering complications
os.write(("4" + System.getProperty("line.separator")).getBytes());
os.flush(); // Doesn't seem to flush.
// os.close(); // uncommenting works, but I'd like to keep the process running
System.out.println("reading");
System.out.println(is.read()); // read even one byte? usually is.available() -> 0
奇怪的是,如果我将 OutputStream 包装在 BufferedWriter 中,我可以从某些进程(cat)中读取,但不能从其他进程(awk、grep)中读取。
【问题讨论】:
-
如果有帮助,请在此处查看我的答案,stackoverflow.com/questions/13008526/…
-
谢谢,阿勒姆。我没有考虑到 stdErr 可能会填满并且消除同步问题是一个不错的方法。但是,在单独的线程中从 stdErr 读取在这里没有帮助。我希望能够将数据推送到进程,让进程工作——例如处理线路或等待任何响应,然后再继续,就像从 shell 运行一样。我应该用 bash -c "..." 结束我的外部进程吗?
-
我没有尝试过在java中运行unix进程但是windows进程,你必须尝试一下。但据我了解,您希望自己而不是系统控制应用程序的退出。为此,您始终可以将 proc.destroy() 放在自定义条件中..??
-
os.close() 和 proc.destroy() 都可以。我的问题是通过进程的输出推送输出内容,如果可用,可以在调用close()或destroy()之前读取。 (bash -c 失败了。)link 对类似问题有否定的结论。同样对于通用进程,外部进程完成输入处理后未定义它,因此使用 Arham 的线程建议可能会产生更清洁的解决方案。
-
别忘了从链接中为我的回答点赞!! :)
标签: java io external-process