Java具有使用Runtimeexec对本地程序调用进行重定向的能力但是用重定向或者管道进行命令调用将会出错解决这一问题的办法是通过命令shell运行命令在Java中调用本地程序会破坏平台独立性规则但是经常需要这么做才行
以下是一个简单类的范例展示了在Unix下运行ls命令的情形
import javaioBufferedInputStream;
import javaioIOException;
public class ExecLs {
static public void main(String[] args) {
String cmd = ls
try {
Process ps = RuntimegetRuntime()exec(cmds);
Systemoutprint(loadStream(psgetInputStream()));
Systemerrprint(loadStream(psgetErrorStream()));
} catch(IOException ioe) {
ioeprintStackTrace();
}
}
// read an inputstream into a String
static String loadStream(InputStream in) throws IOException {
int ptr = ;
in = new BufferedInputStream(in);
StringBuffer buffer = new StringBuffer();
while( (ptr = inread()) != ) {
bufferappend((char)ptr);
}
return buffertoString();
}
}
上述代码中重要的部分是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的全路径有利于提供你的程序的安全性
虽然使用Runtimeexec不是创建独立于平台的Java的最佳方式但是有些时候是必要的使用这种重定向技术有助于走出Runtimeexec的限制