gal*_*gal 93 java runtime.exec processbuilder
我正在尝试从java代码执行一个外部命令,但是我注意到Runtime.getRuntime().exec(...)和之间存在差异new ProcessBuilder(...).start().
使用时Runtime:
Process p = Runtime.getRuntime().exec(installation_path +
uninstall_path +
uninstall_command +
uninstall_arguments);
p.waitFor();
Run Code Online (Sandbox Code Playgroud)
exitValue为0,命令终止ok.
但是,有ProcessBuilder:
Process p = (new ProcessBuilder(installation_path +
uninstall_path +
uninstall_command,
uninstall_arguments)).start();
p.waitFor();
Run Code Online (Sandbox Code Playgroud)
退出值为1001,命令终止于中间,但waitFor返回.
我该怎么做才能解决问题ProcessBuilder?
Luk*_*ard 95
采用Runtime.getRuntime().exec(...)字符串数组或单个字符串的各种重载.exec()在将字符串数组传递给exec()带有字符串数组的重载之一之前,单字符串重载会将字符串标记为参数数组.的ProcessBuilder构造,在另一方面,只需要串的可变参数阵列或List字符串,其中假定该阵列或列表中的每个字符串为一个单独的参数的.无论哪种方式,获得的参数然后被连接成一个字符串,该字符串被传递给OS来执行.
所以,例如,在Windows上,
Runtime.getRuntime().exec("C:\DoStuff.exe -arg1 -arg2");
Run Code Online (Sandbox Code Playgroud)
将DoStuff.exe使用两个给定的参数运行程序.在这种情况下,命令行会被标记化并重新组合在一起.然而,
ProcessBuilder b = new ProcessBuilder("C:\DoStuff.exe -arg1 -arg2");
Run Code Online (Sandbox Code Playgroud)
将失败,除非恰好是他的名字是一个程序DoStuff.exe -arg1 -arg2在C:\.这是因为没有令牌化:假设运行的命令已被标记化.相反,你应该使用
ProcessBuilder b = new ProcessBuilder("C:\DoStuff.exe", "-arg1", "-arg2");
Run Code Online (Sandbox Code Playgroud)
或者
List<String> params = java.util.Arrays.asList("C:\DoStuff.exe", "-arg1", "-arg2");
ProcessBuilder b = new ProcessBuilder(params);
Run Code Online (Sandbox Code Playgroud)
Cos*_*atu 17
看看如何Runtime.getRuntime().exec()将String命令传递给ProcessBuilder.它使用一个标记化器并将命令分解为单个标记,然后调用exec(String[] cmdarray, ......)构造一个标记ProcessBuilder.
如果ProcessBuilder使用字符串数组而不是单个字符串构造,则会得到相同的结果.
所述ProcessBuilder构造函数采用一个String...可变参数,以便使整个命令作为一个单一的字符串与调用相同的效果,即在在终端引号命令:
shell$ "command with args"
Run Code Online (Sandbox Code Playgroud)
Ste*_*n C 13
是,有一点不同.
该Runtime.exec(String)方法采用单个命令字符串,将其拆分为命令和参数序列.
该ProcessBuilder构造采用串的(可变参数)阵列.第一个字符串是命令名称,其余的是参数.
所以你告诉ProcessBuilder要做的是执行一个名称中包含空格和其他垃圾的"命令".当然,操作系统找不到具有该名称的命令,并且命令执行失败.
Eug*_*kin 11
有没有什么区别ProcessBuilder.start()和Runtime.exec()由于实施的Runtime.exec()是:
public Process exec(String command) throws IOException {
return exec(command, null, null);
}
public Process exec(String command, String[] envp, File dir)
throws IOException {
if (command.length() == 0)
throw new IllegalArgumentException("Empty command");
StringTokenizer st = new StringTokenizer(command);
String[] cmdarray = new String[st.countTokens()];
for (int i = 0; st.hasMoreTokens(); i++)
cmdarray[i] = st.nextToken();
return exec(cmdarray, envp, dir);
}
public Process exec(String[] cmdarray, String[] envp, File dir)
throws IOException {
return new ProcessBuilder(cmdarray)
.environment(envp)
.directory(dir)
.start();
}
Run Code Online (Sandbox Code Playgroud)
所以代码:
List<String> list = new ArrayList<>();
new StringTokenizer(command)
.asIterator()
.forEachRemaining(str -> list.add((String) str));
new ProcessBuilder(String[])list.toArray())
.environment(envp)
.directory(dir)
.start();
Run Code Online (Sandbox Code Playgroud)
应该是这样的:
Runtime.exec(command)
Run Code Online (Sandbox Code Playgroud)
感谢dave_thompson_085的评论
| 归档时间: |
|
| 查看次数: |
107685 次 |
| 最近记录: |