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的限制。