5

我正在与 Java 的 Runtime exec 方法中的空格错误作斗争。这是这个问题的独特之处:我试图执行的命令是一个传入的字符串,可能有也可能没有空格,不一定是任何特定的格式。无论哪种方式,我都需要执行它。如果没有空格,我很好;如果有空格,我就不那么好了。

我如何考虑这两种情况?

无需额外费用的奖励信息:一个大问题似乎是我试图在 c:\program files\blablabla... 中调用一个可执行文件,而 exec 似乎在 'c:\program' . 我相信参数也会出现其他问题。

这是我可能得到的字符串类型的更具体示例。这应该可以消除一些困惑:

  • c:\someApp\someapp.exe
  • c:\someApp\someapp.exe -someParam=foo
  • c:\程序文件\someapp\someapp.exe
  • c:\程序文件\someapp\someapp.exe -someParam=bar

第一个工作正常,因为它没有空格。第二个甚至可以,因为它在空间上拆分并使用第一个作为命令,第二个作为参数。第三个和第四个例子在第一个空格上分开,使用'C:\program'和命令'files...'和(在第四个字符串的情况下)'-someParam=bar'作为参数。

4

6 回答 6

4

我实际上会将此作为答案而不是评论:(来自 J2SE 1.5,Runtime.exec(String[])

假设您可以预处理,使用字符串数组来缓解命令中的空格问题,以下应该可以工作:

String[] args = {"C:\Program Files\app\app.exe","C:\Data Files\data1.dat"};
Runtime.exec(args);

从那里它取决于能够弄清楚两个命令之间的空格是什么以及路径中的空格是什么。

编辑

如果空格出现在可执行文件的路径中,这将起作用,但不会帮助您处理参数中的空格。

String input = "c:\\program files\\someapp\\someapp.exe -someParam=bar";
int firstSplit = input.indexOf(".exe") + 4; //account for length of ".exe"
String command = input.substring(0,firstSplit);
String args = input.substring(firstSplit).trim(); //trim off extraneous whitespace
String[] argarray = args.split(" ");
String[] cmdargs = new String[argarray.length + 1];
cmdargs[0] = command;
for (int i = 0; i < argarray.length; i++) {
    cmdargs[i+1] = argarray[i];
}
Runtime.exec(cmdargs);

请注意,这仍然相当脆弱(仅适用于 exe,不适用于 bat 或其他任何东西)。如果您需要考虑参数中的空格,则需要对args字符串或argarray. 正确的解决方案是让您的用户(或输入过程)正确区分所有参数。

于 2010-11-01T16:55:53.963 回答
4

好的,我通过做这样的事情得到了一些工作。请告诉我这种方法是否有问题:


try{
    String[] command = {"cmd", "/c", getMySuperAwesomeString()};
    Runtime.getRuntime().exec(command);
}catch(IOExecption ioe){
    System.err.println("I'm borken");
}

在相关说明中,我应该改用 ProcessBuilder 吗?

于 2010-11-01T17:31:36.240 回答
1

运行文件位置中包含空格的 JAR 文件的示例:

String qoutation = "\""
String path = "C:\\JAR File\\File.jar"
Runtime.getRuntime().exec("java -jar " + quotation + path + quotation);

这运行命令: java -jar "C:\Jar File\File.jar"

When the backslash \ appears in a string it is used as an escape, effectively making the program skip it. This allows us to use the quotation mark " in the string, not to start/close the string.

于 2013-01-21T10:20:42.760 回答
0

也许我想得太简单了,但这能行吗?

Runtime.exec(commandstring.split(" "));

(我假设您希望命令像在 shell 中执行一样执行。)

于 2010-11-01T16:34:45.047 回答
0

我假设您可以预处理传入的字符串。在这种情况下,您可以查看是否有带有空格的输入:

if("string with possible spaces".contains(" ")) {
    System.out.println("yay");
}

请注意,这仅在您的输入中有实际空格字符时才有效。如果您想更彻底,假设制表符或换行符是可能的输入,您可以使用正则表达式:

String s = ".+\\s.+";
Pattern p = Pattern.compile(s);

Matcher m = p.matcher("string with possible spaces or    tabs");
if(m.matches()) {
    System.out.println("yay");
}

编辑:您可以使用我提供的代码来检测输入中是否有空格。如果没有,您无需执行任何操作。如果你有空格,情况会更复杂一些。阅读其他人的答案和您修改后的问题,我只能假设必须引用具有空格的输入,因此空格不会弄乱标准命令执行。在有空格的情况下,您应该:

  1. 检查您的输入中是否有引号
  2. 如果有,请转义它们(更改"\"
  3. 用引号包围输入(some input变成"some input"

最终,您希望输入some "funky" input成为"some \"funky\" input".

注意:注意单引号 ( ')。适当地对待他们。

于 2010-11-01T16:50:31.393 回答
0

我假设这是您正在解决的错误:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4506936

http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=8582245ba20fa4da33ac0967e858?bug_id=4491217

他们说解决方法是:

使用不在包含空格的路径中的 JRE。

使用公共进程 exec(String[] cmdarray, String[] envp) 抛出 IOException

并将命令和参数放在单独的数组中。这样它就不会尝试对其进行标记并使用空格作为分隔符。

于 2010-11-01T16:55:37.263 回答