1. 程式人生 > >java呼叫本地命令

java呼叫本地命令

Java具有使用Runtime.exec對本地程式呼叫進行重定向的能力,但是用重定向或者管道進行命令呼叫將會出錯。解決這一問題的辦法是通過命令shell執行命令。在Java中呼叫本地程式會破壞平臺獨立性規則,但是經常需要這麼做才行。


以下是一個簡單類的範例,展示了在Unix下執行ls命令的情形:

import java.io.BufferedInputStream;
import java.io.IOException;

public class ExecLs {

    static public void main(String[] args) {
        String cmd = "ls"

        try {
            Process ps = Runtime.getRuntime().exec(cmds);
            System.out.print(loadStream(ps.getInputStream()));
            System.err.print(loadStream(ps.getErrorStream()));
        } catch(IOException ioe) {
            ioe.printStackTrace();
        }
    }

    // read an input-stream into a String
    static String loadStream(InputStream in) throws IOException {
        int ptr = 0;
        in = new BufferedInputStream(in);
        StringBuffer buffer = new StringBuffer();
        while( (ptr = in.read()) != -1 ) {
            buffer.append((char)ptr);
        }
        return buffer.toString();


    }

}

上述程式碼中重要的部分是exec方法和命令字串ls。本程式將輸出執行目錄下的列表細節。

那麼,如果你想重定向這些細節內容到檔案該怎麼辦?這一命令列的輸入應該寫成ls > FILE,但是當你將cmd變數改變成這樣的話,執行就會出錯,如下:

/bin/ls: >: No such file or directory
/bin/ls: FILE: No such file or directory

出錯的原因在於額外的引數被直接傳送到了ls命令而不是送到實際的命令列。解決這一問題的辦法是將cmd串弄成一個字串陣列,並且將你想執行的程式傳送到命令shell。

因此,將cmd行改成下面的樣子:

String[] cmd = { "sh", "-c", "ls > FILE" };

你將得到一個名為FILE的檔案,裡面是目錄列表。-c引數是告訴它讀取隨後的字串,而最後的引數是你要執行的指令碼。

在這種情況下,管道也執行良好,所以你可以把命令改成下面的方式:

String[] cmd = { "/bin/sh", "-c", "/bin/ls | grep d > FILE" };

這種形式將給你一個名為FILE的檔案,裡面是ls條目中包含d的條目。給出sh和ls的全路徑有利於提供你的程式的安全性。

雖然使用Runtime.exec不是建立獨立於平臺的Java的最佳方式,但是有些時候是必要的。使用這種重定向技術有助於走出Runtime.exec的限制。