J'essaie de créer une application frontend en Java pour gérer les conversions SVG par lots en utilisant la fonction de ligne de commande d'Inkscape. Je prends et met à jour le code de https://sourceforge.net/projects/conversionsvg/. La façon dont le développeur d'origine a géré l'appel d'Inkscape par Runtime.getRuntime(). Exec (String). Le problème que je rencontre est quelques incohérences entre l'utilisation de methodA et methodB. J'ai créé un projet de test java simple pour démontrer les différentes actions effectuées.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();
}
}
Résultat
deux methodA (String) appels de travail, mais quand methodB (String []) est appelé Inkscape est en cours de démarrage et les arguments sont transmis de façon incorrecte. Après methodB (String []) exécute je reçois un message d'erreur Inkscape pour chaque dire
Impossible de charger le fichier demandé -f C: /test.svg -D -w 100 -h 100 -e C : \ RuntimeExec-methodB.png
Impossible de charger le fichier demandé -f C: /test.svg -D -w 100 -h 100 -e C: \ ProcessBuilder-methodB.png
et Lorsque je clique sur Fermer dans la boîte de dialogue, Inkscape apparaît avec un nouveau document vide. Donc, je suppose que j'ai quelques questions:
Quelle est la différence entre Runtime.getRuntime(). Exec (String) et Runtime.getRuntime(). Exec (String [])?
JavaDoc dit que Runtime.exec (chaîne) appels Runtime.exec (commande, null) (qui est Runtime.exec (String cmd, String [] envp)) qui retourner les appels Runtime.exec (cmdarray, envp) (qui est Runtime.exec (String [] cmdarray, String [] envp)). Donc, si Runtime.getRuntime(). Exec (String) appelle Runtime.exec (String []) de toute façon, pourquoi ai-je des résultats différents lorsque j'utilise différentes méthodes?
Y a-t-il quelque chose derrière les coulisses où Java configure différemment l'environnement en fonction de la méthode appelée?
Je suis à peu près sûr que Java gère la séparation des arguments dans 'ProcessBuilder' ou 'Runtime.exec()', mais autrement correct. – Jonathan
@Jonathan, un coup d'œil sur Runtime montre que vous avez raison - StringTokenizer est utilisé pour décomposer la chaîne sur les espaces. Ce qui signifie que si vous avez des espaces dans le chemin de votre exécutable, vous devrez utiliser Runtime.exec (String []). – userkci