2010-11-20 59 views
6

我需要以用户可以与刚启动的程序进行交互的方式启动外部可执行文件。使用流重定向从Java代码启动外部可执行文件

例如在OpenSuse Linux中有一个包管理器 - Zypper。你可以在命令模式下启动zypper,并给它安装,更新,删除等命令。

我想以一种用户可以与之交互的方式从Java代码运行它:输入命令并查看他开始的程序的输出和错误。

这里是一个Java代码中,我试图用:

public static void main(String[] args) throws IOException, InterruptedException { 
    Process proc = java.lang.Runtime.getRuntime().exec("zypper shell"); 

    InputStream stderr = proc.getInputStream(); 
    InputStreamReader isr = new InputStreamReader(stderr); 
    BufferedReader br = new BufferedReader(isr); 
    String line = null; 
    char ch; 

    while ((ch = (char)br.read()) != -1) 
     System.out.print(ch); 

    int exitVal = proc.waitFor(); 
    System.out.println("Process exitValue: " + exitVal); 
} 

但不幸的是,我只能看到它的输出:

zypper> 

但不管我写的东西,我的输入不影响开始的程序。 我该怎么做才能做到?

回答

2

你需要为了写过程中得到的输出流:

OutputStream out = proc.getOuptutStream(); 

这个输出流通过管道输送到进程的标准输入流,所以你可以只写它(也许你首先要将其包装在PrintWriter中),并将数据发送到进程的标准输入。

请注意,获取错误流(proc.getErrorStream)以便读取进程写入其stderr的任何错误输出可能也很方便。

API参考:

+0

谢谢您的回答。这有帮助! – 2010-11-20 14:07:33

0

好像while条件在你的榜样失败里面的转换,这似乎更好的工作(我不运行Suse的,所以我没有与zypper的试过):

public static void main(String[] args) throws IOException, InterruptedException 
{ 
    //Process proc = java.lang.Runtime.getRuntime().exec("zypper shell"); 
    Process proc = java.lang.Runtime.getRuntime().exec("ping -t localhost"); 

    InputStream stderr = proc.getInputStream(); 
    InputStreamReader isr = new InputStreamReader(stderr); 
    BufferedReader br = new BufferedReader(isr); 

    int i; 
    while ((i = br.read()) != -1) 
    { 
     System.out.print((char) i); 
    } 

    int exitVal = proc.waitFor(); 
    System.out.println("Process exitValue: " + exitVal); 
} 
0

我最近包裹谷歌关闭编译成被提取并且在过程中使用一个.jar文件。这个编译器只能通过System.in/out/err进行通信。连接管道有一个很大的“陷阱”,这只是在流程javadoc中简单提及。

“......没有及时写 输入流或读取子进程的输出流 可能导致 子进程阻塞,甚至 僵局。”

在Mac OS X上,缓冲区为16k,如果您没有按照建议立即读取它,则进程会死锁。我唯一的解决这个问题的ATM,是一个相当讨厌的忙等待。

https://github.com/algesten/googccwrap/blob/master/src/main/java/googccwrap/GoogleClosureCompilerWrapper.java