java - 如何告诉 Java JAR 文件中正确的文件路径?

标签 java javafx java-11 openjfx

我已将所有 JavaFX 代码放入可执行 JAR 文件中。一切都在里面。

当我使用 Eclipse IDE 编译它时,它可以工作,但是当我尝试执行 JAR 文件时,出现错误。

Caused by: javafx.fxml.LoadException: 
file:/home/asus/program/JUSBPlotter/JUSBPlotter-0.0.1-SNAPSHOT-jar-with-dependencies.jar!/se/danielmartensson/fxml/front.fxml

当我有这个Java代码时

 Parent root = FXMLLoader.load(getClass().getResource("/se/danielmartensson/fxml/front.fxml"));

FXML 文件没有任何问题。

fx:controller="se.danielmartensson.controller.Front"

当我尝试在 JavaFX 中显示图片时,我也遇到错误。

Caused by: java.io.FileNotFoundException: file:/home/asus/program/JUSBPlotter/JUSBPlotter-0.0.1-SNAPSHOT-jar-with-dependencies.jar!/se/danielmartensson/pictures/computer.png (No such file or directory)

当我有这个 Java 代码时:

FileInputStream picture1 = new FileInputStream(getClass().getResource("/se/danielmartensson/pictures/computer.png").getFile());

问题: 如何告诉 Java JAR 文件中正确的文件路径?

最佳答案

要记住的一件事是,资源与文件不同,尽管它们看起来非常相似——尤其是在打包应用程序之前。一旦打包应用程序,这些资源文件就会成为 JAR 文件中的条目,虽然它们可以被视为文件,但不能像文件一样进行访问。特别是java.io.File API 不知道如何读取这些条目。但是,您可以通过URL访问这些条目。返回者 Class#getResource(String) InputStream返回者 Class#getResourceAsStream(String) 。请注意,后者基本上只是找到 URL并且,如果存在,则调用 URL#openStream() 。您可以使用 URL 访问 JAR 条目(即资源)的原因是由于 JarURLConnection 及相关类(class);我不会详细介绍 Java 如何处理 URL,因为这超出了本答案的范围。

现在,由于您尝试在 JavaFX 中显示图像,我假设您正在使用 Image 类(class)。基本上可以通过三种方式来辨别 Image图片资源在哪里。

  1. 使用 Image#<init>(String) 其中参数 URL 没有方案。在这种情况下,类会将 URL 视为相对于类路径根的路径,并尝试相应地访问图像。基本上,该参数与您为 Class#getResource(String) 提供的参数相同。 ,但路径必须是绝对路径(即不相对于任何类)。 Image 记录了此行为类:

    All URLs supported by URL can be passed to the constructor. If the passed string is not a valid URL, but a path instead, the Image is searched on the classpath in that case.

    注意:如果您使用模块,则 resource encapsulation使用此选项时发挥作用。请参阅GitHub Issue #441 .

  2. 使用与上面相同的构造函数,但传递一个有效的 URL(即它有一个方案)。使用资源时,只需将 URL 转换即可返回者 Class#getResource(Sring)进入String使用 URL#toExternalForm() .

    Image image = new Image(getClass().getResource(...).toExternalForm());
    

    注意:您还可以使用 URL#toString()返回相同的值。

  3. 使用 Image#<init>(InputStream) 。这里你可以使用Class#getResourceAsStream(String) 。不要忘记关闭InputStream完成后。

    try (InputStream is = getClass().getResourceAsStream(...)) {
        Image image = new Image(is);
    }
    

所有这些都假设您在构建 JAR 文件时已将资源正确打包到该文件中。如果不是这种情况,请先遵循 José Pereda 在问题评论中给出的建议。

<小时/>

请注意,可以使用 java.util.zip.* 访问 ZIP/JAR 文件的条目。 API,java.util.jar.* API,或 Java NIO 的 ZipFileSystemProvider 。其中每个选项(尤其是最后一个选项)都允许您像实际文件一样访问 ZIP/JAR 文件的条目,因为它们是专门为此设计的。但是,在应用程序中使用资源时,您应该坚持使用 Class#getResource(String)以及相关方法。

关于java - 如何告诉 Java JAR 文件中正确的文件路径?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56386935/

相关文章:

java - 由以下原因引起:org.gradle.process.internal.ExecException:Proceorg.gradle.api.tasks.TaskExecutionException:任务 ':service:bootRun'的执行失败

java - Android 中带有复选框的 ListActivity

java - liquibase 和 orai18n.jar

java - 如何在一段时间间隔后生成新的随机整数?

checkbox - JavaFX CSS 复选框样式

java - java认证考试的重载方法

java - 如何修复Java中的 "looping and candidate voting"错误

javafx - JAVAFX在单击按钮时尝试播放声音的问题

JavaFX:禁用使用键盘控制 RadioButtons

java - java.net.HttpClient 状态为 CLOSE_WAIT 的连接泄漏