【问题标题】:Java ProcessBuilder Error When Space(s) In Path路径中有空格时出现 Java ProcessBuilder 错误
【发布时间】:2017-06-07 18:36:03
【问题描述】:

所以我花了 半天 试图让它发挥作用,但没有得到积极的结果。我正在使用 Java ProcessBuilder 来执行一些带有几个参数的 .exe 文件,但文件路径包含空格,不知何故我无法让它正常工作。我检查了许多其他 SO 帖子并实施了解决方案,例如带有转义引号的环绕代码并将其拆分为命令和参数等。我的代码如下:

try {
    ProcessBuilder pBuilder = new ProcessBuilder(
        // Main Command.
        "C:\\namewith space\\database\\postgres_db\\bin\\pg_ctl.exe",
        // Command Parameters.
        "start",
        "-D C:\\namewith space\\database\\database",  
        /*The quotes in the next argument are necessary, the -o stands for 'options' and everything between the quotes are the actual database parameters which to start the Database with.*/
        "-o \"-p 15000\"",
        "-l C:\\namewith space\\database\\postgres_db\\bin\\postgres_log.txt");

    File log = new File("\"C:\\folder\\log.txt\"");
    pBuilder.redirectErrorStream(true);
    pBuilder.redirectOutput(Redirect.appendTo(log));
    Process p = pBuilder.start();
    } catch (IOException ex) {
        System.out.println("Exception Occurred: " + ex);
    }

到目前为止我已经尝试过:

  • 用转义引号包围而不是包围上述代码中的每个/任何路径,以防万一(有人告诉我它确实...)。
  • 使用Runtime.getRuntime().exec("full command with/without any/all escaped quotes"); 方法,但是在搜索 SO 时,我发现每个人都说您应该改用 ProcessBuilder。
  • 在 ProcessBuiler 的第一个命令字符串中以不同方式将上述代码的部分添加在一起,例如 "\"C:\\namewith space\\database\\postgres_db\\bin\\pg_ctl.exe\" start"
  • 这些文件 100% 位于给定路径,我手动检查了这一点,并在文件资源管理器中粘贴了 10 次以上的路径。
  • 将命令拆分为将命令的工作目录设置为 C:\namewithspace\,然后添加不带该部分的 args。

我不断收到的错误(通过System.out.println("Exception Occurred: " + ex);)是:java.io.IOException: Cannot run program "C:\namewith space\database\postgres_db\bin\pg_ctl.exe":文件名、目录名或卷标语法不正确。

如果您需要任何额外的零件/代码,请告诉我,我会尽力提供详细信息。

【问题讨论】:

  • 我不认为修复目录名称或在没有空格的情况下创建指向该路径的符号链接是可行的选择吗?如果这些是您唯一的选择,我不会感到惊讶。该错误消息看起来像是来自操作系统,而不是来自 Java。
  • 不能更改 dirName。但是,如果我在命令提示符中复制/粘贴完全相同的完整语句,包括引号,它就可以工作。如果您也将其放入 .bat 文件中,也可以使用。请告诉我更多关于什么是系统链接。
  • symlink 是一个文件,它只是指向磁盘上另一个位置的指针。
  • 另外,请使用异常的完整堆栈跟踪更新您的问题。

标签: java processbuilder spaces


【解决方案1】:

尝试分解问题。

首先只需将 IOException 中显示的绝对路径读入一个 File 对象,然后调用 exists() 方法来检查该文件是否确实存在并且 JVM 可以访问它。

如果这不起作用,请修复您的路径或访问权限。如果文件确实存在并且您可以访问它,则创建 ProcessBuilder不带任何参数,只需使用您的 exe 的绝对路径。

你现在不应该得到 IOException。 然后一一添加参数。如果你发现一个破坏了事情,那么修复参数(可能缺少双引号)并继续下一个直到你完成。

【讨论】:

  • 创建了一个新的 File 对象,其中包含我要访问的文件的路径。 myFile.exists() 返回真。所以程序可以访问它,这是一件好事。然后添加完全相同的路径(路径周围有或没有额外的转义引号)返回 IOException。 Screenshot of the output.
  • 如果你在文件对象上调用getAbsolutePath()方法并且你使用返回的字符串作为命令,这样行吗?
  • 这实际上正是我所做的:/ 使用该路径创建了一个新的 File 对象,然后使用 myFile.exists() 检查该文件是否可以通过代码访问,然后创建像 new ProcessBuilder(myFile.getAbsolutPath()) 这样的 pBuilder没有任何其他参数。
  • 我刚刚尝试过,它成功了:ProcessBuilder pb = new ProcessBuilder("C:\\my dir with spaces\\whatever\\my.exe"); pb.start()
  • 在这种情况下,比较(逐字节,如有必要)该字符串的内容与myFile.getAbsolutePath() 的结果,您会发现错误。我的猜测是有一些不寻常的字符被传递给File 对象,File API 能够处理,但 Windows 不能。
最近更新 更多