如何告诉 Java JAR 文件中的正确文件路径?
How to tell Java the correct file path in a JAR-file?
我已将所有 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 不理解如何阅读这些条目。但是,您可以通过 Class#getResource(String)
or the InputStream
returned by Class#getResourceAsStream(String)
. Note the latter basically just finds the URL
and, if it exists, calls URL#openStream()
. The reason you can access JAR entries (i.e. resources) with the URL
is due to the JarURLConnection
和相关 class 返回的 URL
访问这些条目;我不会详细介绍 Java 如何处理 URL,因为这超出了这个答案的范围。
现在,由于您正尝试在 JavaFX 中显示图像,我假设您使用的是 Image
class。基本上可以通过三种方式告诉 Image
图片资源在哪里。
在参数 URL 没有方案的地方使用 Image#<init>(String)
。在这种情况下,class 会将 URL 视为相对于 class 路径根的路径,并相应地尝试访问图像。基本上,该参数与您给 Class#getResource(String)
的参数相同,除了路径必须是绝对路径(即不相对于任何 class)。此行为由 Image
class:
记录
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 comes into play when using this option. See GitHub Issue #441.
使用与上面相同的构造函数,但传递一个有效的 URL(即它有一个方案)。使用资源时,您可以使用 URL#toExternalForm()
.
将 Class#getResource(Sring)
返回的 URL
简单地转换为 String
Image image = new Image(getClass().getResource(...).toExternalForm());
注意:您也可以使用URL#toString()
其中returns相同的值。
使用Image#<init>(InputStream)
。这里可以使用Class#getResourceAsStream(String)
。不要忘记在完成后关闭 InputStream
。
try (InputStream is = getClass().getResourceAsStream(...)) {
Image image = new Image(is);
}
所有这些都假定在您构建 JAR 文件时资源已正确打包。如果不是这种情况,请首先遵循 José Pereda 在问题评论中给出的建议。
请注意,可以使用 java.util.zip.*
API、java.util.jar.*
API 访问 ZIP/JAR 文件的条目,或者 Java NIO 的 ZipFileSystemProvider
。其中每一个,尤其是最后一个选项,都允许您访问类似于实际文件的 ZIP/JAR 文件的条目,因为它们是专门为此设计的。但是,在应用程序中使用资源时,您应该坚持使用 Class#getResource(String)
和相关方法。
我已将所有 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 不理解如何阅读这些条目。但是,您可以通过 Class#getResource(String)
or the InputStream
returned by Class#getResourceAsStream(String)
. Note the latter basically just finds the URL
and, if it exists, calls URL#openStream()
. The reason you can access JAR entries (i.e. resources) with the URL
is due to the JarURLConnection
和相关 class 返回的 URL
访问这些条目;我不会详细介绍 Java 如何处理 URL,因为这超出了这个答案的范围。
现在,由于您正尝试在 JavaFX 中显示图像,我假设您使用的是 Image
class。基本上可以通过三种方式告诉 Image
图片资源在哪里。
在参数 URL 没有方案的地方使用
记录Image#<init>(String)
。在这种情况下,class 会将 URL 视为相对于 class 路径根的路径,并相应地尝试访问图像。基本上,该参数与您给Class#getResource(String)
的参数相同,除了路径必须是绝对路径(即不相对于任何 class)。此行为由Image
class: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 comes into play when using this option. See GitHub Issue #441.
使用与上面相同的构造函数,但传递一个有效的 URL(即它有一个方案)。使用资源时,您可以使用
将URL#toExternalForm()
.Class#getResource(Sring)
返回的URL
简单地转换为String
Image image = new Image(getClass().getResource(...).toExternalForm());
注意:您也可以使用
URL#toString()
其中returns相同的值。使用
Image#<init>(InputStream)
。这里可以使用Class#getResourceAsStream(String)
。不要忘记在完成后关闭InputStream
。try (InputStream is = getClass().getResourceAsStream(...)) { Image image = new Image(is); }
所有这些都假定在您构建 JAR 文件时资源已正确打包。如果不是这种情况,请首先遵循 José Pereda 在问题评论中给出的建议。
请注意,可以使用 java.util.zip.*
API、java.util.jar.*
API 访问 ZIP/JAR 文件的条目,或者 Java NIO 的 ZipFileSystemProvider
。其中每一个,尤其是最后一个选项,都允许您访问类似于实际文件的 ZIP/JAR 文件的条目,因为它们是专门为此设计的。但是,在应用程序中使用资源时,您应该坚持使用 Class#getResource(String)
和相关方法。