2010-11-20 60 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