如何在可导出库中正确设置资源
How to correctly setup resources in a exportable library
在我创建的库中,我有以下行来检索我的资源:
private static final File fragment = new File(DefaultShader.class.getClassLoader().getResource("file.txt").getFile());
但是当我将此库导出到 JAR 并尝试在另一个应用程序中使用它时,当在内部读取同一行时,我收到 I/O 错误,因为它正在尝试访问 JAR。
java.io.FileNotFoundException: file:\C:\Users\me\test\libs\lib.jar!\file.txt
Nodejs 会通过提供 returns 脚本的运行时位置路径的方法使这更容易,显然 Java 中没有等效项或者只是找不到它。我怎样才能解决这个问题?
永远不要调用 URL 的 getFile 方法。它不是 return 有效的文件名。它只是 return 的路径部分 URL。
.jar 文件中嵌入的资源不是文件,您不能将其称为文件。
幸运的是,您不需要 File 对象。您可以直接使用 getResourceAsStream:
阅读
DefaultShader.class.getResourceAsStream("/file.txt")
显然,您不应将 InputStream 存储在 static final
字段中。但是您可以轻松地创建一个方法:
private static InputStream readFileData() {
return DefaultShader.class.getResourceAsStream("/file.txt");
}
请注意,资源应该放在包中,就像 classes 一样。将资源放在 .jar 的根目录中就像将文件写入驱动器的根目录或用户的主目录:如果任何其他程序选择使用相同的文件名,至少可以说这两个程序的结果都会有问题.
同理,如果你的资源在你的.jar的根目录下,而另一个库恰好在自己的.jar的根目录下也存放了一个同名的资源,就会产生冲突,可能或者可能不是由 getResource* 方法加载的资源,具体取决于当前的 classpath 定义。 (此问题不适用于 Java 9+ 模块化程序,但将资源保存在包中仍然是个好主意。)
将资源与使用它的 class 放在同一个包中的做法被 Java SE 认为是一个很好的做法:getResource
和 getResourceAsStream
默认情况下,方法被设计为期望它与 class 在同一个包中。如果字符串参数不以斜杠开头,这些方法会假定它在同一个包中。
这会在与 DefaultShader class 相同的包中查找 file.txt:
DefaultShader.class.getResourceAsStream("file.txt")
而这将在 class 路径中的每个 .jar 的根目录中查找 file.txt:
DefaultShader.class.getResourceAsStream("/file.txt")
在我创建的库中,我有以下行来检索我的资源:
private static final File fragment = new File(DefaultShader.class.getClassLoader().getResource("file.txt").getFile());
但是当我将此库导出到 JAR 并尝试在另一个应用程序中使用它时,当在内部读取同一行时,我收到 I/O 错误,因为它正在尝试访问 JAR。
java.io.FileNotFoundException: file:\C:\Users\me\test\libs\lib.jar!\file.txt
Nodejs 会通过提供 returns 脚本的运行时位置路径的方法使这更容易,显然 Java 中没有等效项或者只是找不到它。我怎样才能解决这个问题?
永远不要调用 URL 的 getFile 方法。它不是 return 有效的文件名。它只是 return 的路径部分 URL。
.jar 文件中嵌入的资源不是文件,您不能将其称为文件。
幸运的是,您不需要 File 对象。您可以直接使用 getResourceAsStream:
阅读DefaultShader.class.getResourceAsStream("/file.txt")
显然,您不应将 InputStream 存储在 static final
字段中。但是您可以轻松地创建一个方法:
private static InputStream readFileData() {
return DefaultShader.class.getResourceAsStream("/file.txt");
}
请注意,资源应该放在包中,就像 classes 一样。将资源放在 .jar 的根目录中就像将文件写入驱动器的根目录或用户的主目录:如果任何其他程序选择使用相同的文件名,至少可以说这两个程序的结果都会有问题.
同理,如果你的资源在你的.jar的根目录下,而另一个库恰好在自己的.jar的根目录下也存放了一个同名的资源,就会产生冲突,可能或者可能不是由 getResource* 方法加载的资源,具体取决于当前的 classpath 定义。 (此问题不适用于 Java 9+ 模块化程序,但将资源保存在包中仍然是个好主意。)
将资源与使用它的 class 放在同一个包中的做法被 Java SE 认为是一个很好的做法:getResource
和 getResourceAsStream
默认情况下,方法被设计为期望它与 class 在同一个包中。如果字符串参数不以斜杠开头,这些方法会假定它在同一个包中。
这会在与 DefaultShader class 相同的包中查找 file.txt:
DefaultShader.class.getResourceAsStream("file.txt")
而这将在 class 路径中的每个 .jar 的根目录中查找 file.txt:
DefaultShader.class.getResourceAsStream("/file.txt")