Java: moyen correct d'échapper la chaîne pour l'appel dépendant du système d'exploitation via l'exécution.getRuntime ().exec()


Dans mon application Java, je dois appeler un autre pot exécutable. Cela ressemble à ceci:

String path_to_jar_file = "/path/to/app.jar";
String some_params      = "-par1 -par2 -par3";

//-- perform system call
Process pr = Runtime.getRuntime().exec("java -jar " + path_to_jar_file + " " + some_params);

//-- echo output
BufferedReader input = new BufferedReader(
      new InputStreamReader(pr.getInputStream())
      );
String line = null;
while ((line = input.readLine()) != null){
   System.out.println(line);
}

//-- wait until process is finished and get its exit code
int exitVal = pr.waitFor();

Mais path_to_jar_file est en fait fourni par l'utilisateur, donc ce chemin pourrait contenir des espaces, ou autre. Sous Windows, je peux simplement le citer, comme ceci:

Runtime.getRuntime().exec("java -jar \"" + path_to_jar_file + "\" " + some_params);

Et ça marche. Mais sur Linux, étonnamment, cela ne fonctionne pas. (aucune exception n'est levée, rien n'est repris, juste le code de sortie est 1, ce qui indique une erreur)

La chose étrange est que si je tape cette commande dans le terminal (avec des guillemets), cela fonctionne! Mais, si je l'appelle via Runtime.getRuntime().exec(), cela ne fonctionne que sans guillemets.

La seule solution que j'ai trouvée est d'utiliser Apache Common SystemUtils.IS_OS_WINDOWS: sous Windows, citez le chemin, et sous linux les espaces d'échappement et autres symboles.

Mais il y a probablement une solution toute faite pour cela?

Author: Dmitry Frank, 2014-02-16

1 answers

J'ai testé votre code et j'ai eu le même problème que vous sur OSX.

Votre problème semble être lié à un espace vide, j'ai pu contourner le problème en utilisant un ProcessBuilder, car il fonctionne beaucoup mieux avec des espaces.

    //Create and start process builder
    ProcessBuilder builder = new ProcessBuilder("java", "-jar", path_to_jar_file, param1, param2, param3);
    Process process = builder.start();

    //Create reader to get error messages (Just in case you have another issue)
    BufferedReader errinput = new BufferedReader(new InputStreamReader(
        process.getErrorStream()));

    //Print errors to the terminal/console
    String s = null;
    while ((s = errinput.readLine()) != null)
    {
        System.out.println(s);
    }

Le code ci-dessus fonctionne sur Windows et OSX, Linux doit se comporter de la même manière que OSX.

N'oubliez pas de retirer le code de rapport d'erreur lorsque vous avez terminé, car il verrouillera le thread principal.

 2
Author: sorifiend, 2014-02-18 01:50:51