I'm trying to create a frontend app in Java to handle batch SVG conversions using Inkscape's command line feature. I'm taking and updating the code from https://sourceforge.net/projects/conversionsvg/. The way the original developer handled calling Inkscape by Runtime.getRuntime().exec(String). The issue I'm running into is some inconsistencies between using methodA and methodB. I created a simple java test project to demonstrate the different actions being performed.
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(); } } Result
Both methodA(String) calls work, but when methodB(String[]) is called Inkscape is being started and the arguments are being passed incorrectly. After methodB(String[]) executes I get an Inkscape error dialog for each saying
Failed to load the requested file -f C:/test.svg -D -w 100 -h 100 -e C:\RuntimeExec-methodB.png
Failed to load the requested file -f C:/test.svg -D -w 100 -h 100 -e C:\ProcessBuilder-methodB.png
and when I click Close on the dialog, Inkscape pops up with a new blank document. So, I guess I have a few questions:
What is the difference between Runtime.getRuntime().exec(String) and Runtime.getRuntime().exec(String[])?
JavaDoc says that Runtime.exec(String) calls Runtime.exec(command, null) (which is Runtime.exec(String cmd, String[] envp)) which in turn calls Runtime.exec(cmdarray, envp) (which is Runtime.exec(String[] cmdarray, String[] envp)). So, if Runtime.getRuntime().exec(String) is calling Runtime.exec(String[]) anyways, why am I getting different results when using different methods?
Is something happening behind the scenes where Java sets up the environment differently depending on which method is called?