Estoy tratando de crear una aplicación frontend en Java para manejar las conversiones SVG por lotes utilizando la función de línea de comando de Inkscape. Estoy tomando y actualizando el código de https://sourceforge.net/projects/conversionsvg/. La forma en que el desarrollador original manejó llamar a Inkscape por Runtime.getRuntime(). Exec (String). El problema al que me estoy enfrentando es algunas inconsistencias entre usar methodA y methodB. Creé un proyecto simple de prueba de Java para demostrar las diferentes acciones que se realizan.ProcessBuilder vs Runtime.exec()
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();
}
}
de Resultados
Tanto MethodA (String) llamadas de trabajo, pero cuando methodB (String []) se llama se va a iniciar Inkscape y los argumentos se pasan de forma incorrecta. Después methodB (String []) ejecuta consigo un diálogo de error Inkscape para decir cada uno
No se pudo cargar el archivo solicitado -f C: /test.svg -D -w 100 -h 100 -e C : \ RuntimeExec-methodB.png
No se ha podido cargar el archivo solicitado -f C: /test.svg -D -w 100 -h 100 -e C: \ ProcessBuilder-methodB.png
y cuando hago clic en Cerrar en el diálogo, aparece Inkscape con un nuevo documento en blanco. Entonces, supongo que tengo algunas preguntas:
¿Cuál es la diferencia entre Runtime.getRuntime(). Exec (String) y Runtime.getRuntime(). Exec (String [])?
JavaDoc dice que Runtime.exec (cadena) llamadas Runtime.exec (mando, null) (que es Runtime.exec (CMD String, String [] envp)) que a su turn llamadas Runtime.exec (cmdarray, envp) (que es Runtime.exec (String [] cmdarray, String [] envp)). Entonces, si Runtime.getRuntime(). Exec (String) llama a Runtime.exec (String []) de todos modos, ¿por qué obtengo resultados diferentes cuando uso diferentes métodos?
¿Hay algo detrás de escena en el que Java configura el entorno de forma diferente según el método que se llame?
Estoy bastante seguro de que Java maneja dividir los argumentos en 'ProcessBuilder' o' Runtime.exec() ', pero de lo contrario correctos. – Jonathan
@Jonathan, un vistazo rápido a Runtime muestra que está en lo cierto: StringTokenizer se usa para dividir la cadena en espacios en blanco. Lo que significa que si tienes espacios en blanco en la ruta de tu ejecutable, necesitarás usar Runtime.exec (String []). – userkci