Использование Java-команды exec, когда вы не знаете, есть ли пробелы - PullRequest
5 голосов
/ 01 ноября 2010

Я борюсь с ошибкой пробелов в исполняемом методе Java Runtime.Вот что является уникальным в этой проблеме: команда, которую я пытаюсь выполнить, является входящей строкой и может содержать или не содержать пробелы и необязательно имеет какой-либо конкретный формат.В любом случае, мне нужно выполнить это.Если нет пробелов, я в порядке;если есть пробелы, я не очень хорош.

Как мне учесть оба обстоятельства?

Информация о бонусе без дополнительной оплаты: одна из больших проблем заключается в том, что я 'я пытаюсь вызвать исполняемый файл в c: \ program files \ blablabla ... и exec, кажется, разделен на месте после 'c: \ program'.Я уверен, что другие параметры возникнут и для параметров.

Вот более конкретный пример типов строк, которые я мог бы получить.Это должно устранить некоторые недоразумения:

  • 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 ]

4 голосов
/ 01 ноября 2010

Хорошо, я получил что-то работающее, сделав что-то вроде этого. Пожалуйста, скажите мне, если есть проблема с этим подходом:


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

В связанной заметке я должен использовать ProcessBuilder вместо этого?

4 голосов
/ 01 ноября 2010

Я на самом деле сделаю это ответом вместо комментария: (из J2SE 1.5, Runtime.exec (строка []) )

Предполагая, что вы можете выполнить предварительную обработку, используя массив String для решения проблем с пробелами в командах, должно работать следующее:

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

Оттуда это зависит от способности выяснить, что такое пробел между двумя командами и что такое пробел в пути.

EDIT

Это сработает, если в пути исполняемого файла появятся пробелы, но не поможет с пробелами в аргументах.

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, а не летучая мышь или что-то еще). Если вам нужно учесть пробелы в аргументах, вам нужно будет больше обрабатывать либо строку args, либо строку argarray. Правильное решение состоит в том, чтобы заставить ваших пользователей (или процесс ввода) правильно дифференцировать все аргументы.

1 голос
/ 21 января 2013

Пример запуска файла 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"

Когда обратная косая черта \ появляется в строке, она используется как escape, что заставляет программу пропустить ее.Это позволяет нам использовать кавычку "в строке, а не начинать / закрывать строку.

0 голосов
/ 01 ноября 2010

Я предполагаю, что это ошибка, с которой вы боретесь:

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

и поместить командупараметры в отдельном массиве.Таким образом, он не будет пытаться взломать его и использовать пробел в качестве разделителя.

0 голосов
/ 01 ноября 2010

Я предполагаю, что вы можете предварительно обработать входящую строку. В этом случае вы можете увидеть, есть ли у вас ввод с пробелами:

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".

Примечание: остерегайтесь одиночных кавычек ('). Иметь дело с ними соответствующим образом.

0 голосов
/ 01 ноября 2010

Может быть, я думаю слишком просто, но может ли это сработать?

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

(я предполагаю, что вы хотите, чтобы команда выполнялась, как если бы она выполнялась в оболочке или около того).

...