Question

I'm fighting the spaces bug in Java's Runtime exec method. Here's what's unique about this problem: the command I'm trying to execute is an incoming string and may or may not have spaces and is not necessarily in any specific format. Either way, I need to execute it. If there are no spaces, I'm good; if there are spaces, I'm not so good.

How do I account for both circumstances?

Bonus info at no extra charge: One of the big issues appears to be that I'm trying to call an executable in c:\program files\blablabla... and exec appears to split on the space after 'c:\program'. I'm sure other issues would come up for the parameters, too.

Here's a more specific example of the kinds of strings I might get. That should clear up some of the confusion:

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

The first one works fine because it has no spaces. The second is even okay because it splits on the space and uses the first as a command and second as a parameter. The third and fourth examples split on the first space, use 'C:\program' and the command, 'files...' and (in the case of the fourth string) '-someParam=bar' as parameters.

Was it helpful?

Solution 2

Okay, I got something working by doing something like this. Please tell me if there's a problem with this approach:


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

On a related note, should I use ProcessBuilder instead?

OTHER TIPS

I'll actually make this an answer instead of a comment: (from the J2SE 1.5, Runtime.exec(String[]))

Assuming you can preprocess, use a String array to alleviate the problems with spaces in commands, the following should work:

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

From there it depends on being able to figure out what is a space between two commands and what is a space in a path.

EDIT

This will work if the spaces appear in the executable's path, but won't help you on spaces in the arguments.

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);

Note that this is still fairly fragile (and only works for exe's, not bat's or whatever else). If you need to account for spaces in the arguments, you'll need to do more processing to either the args string or the argarray. The proper solution is to get your users (or the input process) to properly differentiate all the arguments.

Example to run a JAR file with spaces in the file location:

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

This runs the command: 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.

Maybe I'm thinking too simply, but could this work?

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

(I'm assuming that you want the command to be executed as if executed in a shell or so.)

I'll assume you can preprocess the incoming string. In that case, you can see if you have an input with spaces with:

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

Note that this will work only if there's an actual space character in your input. If you want to be more thorough, assuming tab characters or newlines are possible inputs, you can use a regex:

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");
}

Edit: You can use the code I provided to detect if there are spaces in the input. If there aren't, you don't have to do anything. If you have spaces, the situation is a bit more complex. Reading other people's answers and your revised question, I can only assume that the input that has spaces has to be quoted, so spacing won't mess up the standard command execution. In there are spaces, you should:

  1. check if there are any quotes in your input
  2. if there are any, escape them (change " to \")
  3. surround the input with quotes (some input becomes "some input")

Ultimately, you want input like some "funky" input to become "some \"funky\" input".

Note: beware of single quotes ('). Deal with them appropriately.

I am assuming this is the bug you are fighting:

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

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

They say that the workaround would be:

Use a JRE that is not located in a path that contains spaces.

Use public Process exec(String[] cmdarray, String[] envp) throws IOException

and put the command and parameters in a separate array. This way it wouldn't try to tockenize it and use space as a separator.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top