当你不知道是否有空格时,使用Java的exec命令

时间:2010-11-01 16:28:18

标签: java process build-process runtime.exec

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

我如何解释这两种情况?

免费获得奖励信息:其中一个重要问题似乎是我试图在c:\ program files \ blablabla中调用可执行文件......并且exec似乎在'c:之后的空格上拆分: \程序'。我也确定参数的其他问题也会出现。

这是我可能得到的各种字符串的更具体的例子。这应该可以解决一些困惑:

  • C:\ someApp \ someapp.exe
  • c:\ someApp \ someapp.exe -someParam = foo
  • c:\ program files \ someapp \ someapp.exe
  • c:\ program files \ someapp \ someapp.exe -someParam = bar

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

6 个答案:

答案 0 :(得分:4)

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

假设您可以预处理,使用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进行更多处理。正确的解决方案是让您的用户(或输入过程)正确区分所有参数。

答案 1 :(得分:4)

好的,我做了类似的工作。请告诉我这种方法是否有问题:


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

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

答案 2 :(得分: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”

当反斜杠\出现在字符串中时,它被用作转义符,有效地使程序跳过它。这允许我们在字符串中使用引号“,而不是开始/关闭字符串。

答案 3 :(得分:0)

也许我的想法太简单了,但这可行吗?

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

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

答案 4 :(得分: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"
  4. 最终,您希望some "funky" input之类的输入成为"some \"funky\" input"

    注意:注意单引号(')。适当地处理它们。

答案 5 :(得分: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。

使用 public Process exec(String [] cmdarray,                     String [] envp)              抛出IOException

并将命令和参数放在一个单独的数组中。这样它就不会试图将它tockenize并使用space作为分隔符。