为什么没有" .."当应用程序部署为JAR时,(两个句点)工作到一个目录?

时间:2018-04-10 04:08:17

标签: java javafx path executable-jar

当我在IDE中运行应用程序时,使用..(两个句点)可以轻松完成accessing the parent directory(相对于当前目录)。

这是一个简单的例子:

包结构

src
└───main
    ├───java
    │   │   Main.java
    │   │
    │   └───controllers
    │           Controller.java
    │           InnerController.java
    │
    └───resources
        └───fxml
                inner-layout.fxml
                layout.fxml

Controller内部,我试着说,"上升一级,然后去找fxml/inner-layout.fxml"。

URL relativeResource = Controller.class.getResource("../fxml/inner-layout.fxml");
// Returns: "file:/C:/Users/BradTurek/IdeaProjects/Parent%20Directory%20Jar%20MCVE/build/resources/main/fxml/inner-layout.fxml"

这适用于文件系统。

但是,当我将应用程序部署为可执行.jar文件时,..不再被解释为"上一个目录"。我检查过:我可以仍然访问.jar中的资源 - 除非我使用包含..的路径。

似乎..在处理.jar内的路径时无法正常工作。

您可以自行下载并运行a full MCVE of the above example

这个问题的答案在互联网上很容易 ,但它可能在那里。我的希望是,我已经清楚地提出了这个问题,以便让其他人轻易找到答案。

为什么会这样?

1 个答案:

答案 0 :(得分:4)

首先,它是说方法Class.getResource(String)没有指定任何支持处理" .."在路上。所以你的问题的答案可以在这里结束:"因为规范没有定义这种行为"

当从IDE内部启动应用程序时它起作用的原因是,在这种情况下,本地文件系统工具用于访问资源。这些能够解决" .."在你的道路上。

但是JAR文件本身不是文件系统 - 它只是一个压缩容器,以非定义的顺序保存所有.class文件和其他资源(请参阅JAR file specification - Oracle)。虽然它符合ZIP文件标准,其中包含一个目录列表,称为“中心目录”。 (参见ZIP (file format) - Wikipedia),在用于解析路径之前,必须首先使用此列表构建树状可导航路径结构。我假设由于性能和内存消耗的原因,没有通过类加载器加载类和其他资源。

但在你的情况下,根本没有理由使用相对路径,因此依赖路径解析。相反,您可以使用绝对路径。这听起来更糟糕,因为这样的绝对路径在文件系统方面并不是真正的绝对路径,但与类路径根目录相关的绝对路径

所以这应该有效:

URL resource = Controller.class.getResource("/fxml/inner-layout.fxml");

无论是从文件系统,JAR文件还是从远程存储库服务器通过HTTP加载资源都无关紧要。