【问题标题】:Java: correct way to escape string for OS-dependent call via Runtime.getRuntime().exec()Java:通过 Runtime.getRuntime().exec() 为依赖于操作系统的调用转义字符串的正确方法
【发布时间】:2014-02-16 15:11:27
【问题描述】:

在我的 Java 应用程序中,我需要调用另一个可运行的 jar。它看起来像这样:

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();

但是path_to_jar_file实际上是由用户提供的,所以这个路径可以包含空格,或者其他什么。 在 Windows 上,我可以像这样引用它:

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

它有效。但在 Linux 上,令人惊讶的是,它不起作用。 (不抛出异常,不回显,只是退出码为1,表示错误)

奇怪的是,如果我在终端中输入这个命令(带引号),它就会起作用!但是,如果我通过 Runtime.getRuntime().exec() 调用它,它只能在没有引号的情况下工作。

我想出的唯一解决方案是使用 Apache Common 的 SystemUtils.IS_OS_WINDOWS :在 windows 上,引用路径,在 linux 上使用转义空格和其他符号。

但可能有一些现成的解决方案?

【问题讨论】:

  • 首先尝试在 linux 终端上手动运行他的命令,然后复制字符串并将其粘贴到 exec 中(作为一个字符串,与终端中的完全一样)然后再试一次。如果这两个都有效,那么您知道这是您在程序中创建字符串/路径/参数的方式的问题。
  • @sorifiend,在我的 Java 程序中,在调用 exec() 之前,我实际上回显了命令:System.out.println(command); 然后我将此命令复制粘贴到终端中,它在那里工作!但是当我通过exec() 执行它时它不会。

标签: java operating-system escaping


【解决方案1】:

我测试了你的代码,在 OSX 上遇到了和你一样的问题。

您的问题似乎与空格有关,我可以通过使用 ProcessBuilder 解决该问题,因为它与空格配合得更好。

    //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);
    }

以上代码适用于 Windows 和 OSX,Linux 的行为方式应该与 OSX 相同。

完成后记得把报错代码拿出来,因为它会锁住主线程。

【讨论】:

  • 非常感谢!我已经在 linux 上使用包含空格和一些特殊字符的路径对其进行了测试,它工作正常。还没有在 Windows 上测试过(路径包含空格),希望它能工作。
猜你喜欢
  • 2011-08-23
  • 1970-01-01
  • 1970-01-01
  • 2011-01-07
  • 1970-01-01
  • 2019-03-18
  • 2017-03-09
  • 2014-04-27
  • 2013-09-01
相关资源
最近更新 更多