Я пытаюсь создать внешнее приложение на Java для обработки пакетных преобразований SVG с использованием функции командной строки Inkscape. Я беру и обновляю код с сайта https://sourceforge.net/projects/conversionsvg/. Способ, которым первоначальный разработчик обрабатывал вызов Inkscape с помощью Runtime.getRuntime().exec(String). Проблема, с которой я сталкиваюсь, заключается в некоторых несоответствиях между использованием метода A и метода B. Я создал простой тестовый проект Java, чтобы продемонстрировать различные выполняемые действия.
CallerTest.java
package conversion;
import java.io.IOException;
public class CallerTest {
static String pathToInkscape = "\"C:\\Program Files\\Inkscape\\inkscape.exe\"";
public static void main(String[] args) {
ProcessBuilderCaller processBuilder = new ProcessBuilderCaller();
RuntimeExecCaller runtimeExec = new RuntimeExecCaller();
// methodA() uses one long command line string
try {
String oneLongString_ProcessBuilder = pathToInkscape + " -f \"C:\\test.svg\" -D -w 100 -h 100 -e \"C:\\ProcessBuilder-methodB.png\"";
String oneLongString_RuntimeExec = pathToInkscape + " -f \"C:\\test.svg\" -D -w 100 -h 100 -e \"C:\\RuntimeExec-methodA.png\"";
// processBuilder.methodA(oneLongString_ProcessBuilder);
runtimeExec.methodA(oneLongString_RuntimeExec);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// methodB() uses an array containing the command and the options to pass to the command
try {
String[] commandAndOptions_ProcessBuilder = {pathToInkscape, " -f \"C:/test.svg\" -D -w 100 -h 100 -e \"C:\\ProcessBuilder-methodB.png\""};
String[] commandAndOptions_RuntimeExec = {pathToInkscape, " -f \"C:/test.svg\" -D -w 100 -h 100 -e \"C:\\RuntimeExec-methodB.png\""};
processBuilder.methodB(commandAndOptions_ProcessBuilder);
// runtimeExec.methodB(commandAndOptions_RuntimeExec);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
RuntimeExecCaller.java
package conversion;
import java.io.IOException;
public class RuntimeExecCaller {
Process process;
// use one string
public void methodA(String oneLongString) throws IOException {
process = Runtime.getRuntime().exec(oneLongString);
}
// use the array
public void methodB(String[] commandAndOptions) throws IOException {
process = Runtime.getRuntime().exec(commandAndOptions);
}
}
ProcessBuilderCaller.java
package conversion;
import java.io.IOException;
public class ProcessBuilderCaller {
Process process;
// use one string
public void methodA(String oneLongString) throws IOException {
process = new ProcessBuilder(oneLongString).start();
}
// use the array
public void methodB(String[] commandAndOptions) throws IOException {
process = new ProcessBuilder(commandAndOptions).start();
}
}
Результат
Оба вызова methodA(String) работают, но когда вызывается methodB(String[]), Inkscape запускается и аргументы передаются неправильно. После выполнения methodB(String[]) я получаю диалоговое окно с ошибкой Inkscape для каждого высказывания
Не удалось загрузить запрошенный файл -f C:/test.svg -D -w 100 -h 100 -e C:\RuntimeExec-methodB.png
Не удалось загрузить запрошенный файл -f C:/test.svg -D -w 100 -h 100 -e C:\ProcessBuilder-methodB.png
и когда я нажимаю «Закрыть» в диалоговом окне, Inkscape появляется с новым пустым документом. Итак, я думаю, у меня есть несколько вопросов:
В чем разница между Runtime.getRuntime().exec(String) и Runtime.getRuntime().exec(String[])?
JavaDoc говорит, что Runtime.exec(String) вызывает Runtime.exec(command, null) (то есть Runtime. exec(String cmd, String[] envp)), который, в свою очередь, вызывает Runtime.exec(cmdarray, envp) (то есть Runtime.exec (String[] cmdarray, String[] envp)). Итак, если Runtime.getRuntime().exec(String) все равно вызывает Runtime.exec(String[]), почему я получаю разные результаты при использовании разных методов?
Что-то происходит за кулисами, когда Java настраивает среду по-разному в зависимости от того, какой метод вызывается?