我在高中时通过lwjgl git book短暂地学习了Java,现在又回到了Java。有一段使用'getResourceAsStream‘函数的片段着色器/顶点着色器应该加载到哪里,这让我有点迷惑。
我尝试了不同的方法,并试图调试/打印JVM搜索文件的位置,但是我有点不知所措。我很困惑,但我也更愿意理解为什么这段代码不能在我的机器上工作,以及如何让它工作(使用这种包/类加载方法)。
因为这两个类都共享“main”类,所以我认为JVM会从那里开始搜索“resources”文件夹。但事实似乎并非如此。
我确实认为这与包声明有关,但我还不够理解,无法继续下去。
以下是相关文件和位置...我试图只包含我认为重要的内容。
// project-root/src/main/java/org/lwjglb/engine/Utils.java
package main.java.org.lwjglb.engine;
// other imports...
public class Utils {
public static String loadResource(String fileName) {
InputStream in = class.forName(Utils.class.getName()).getResourceAsStream(fileName);
// 'in' is null after this call
// other code...
}
}
// project-root/src/main/java/org/lwjglb/game/Renderer.java
import main.java.org.lwjgl.engine.Utils;
// other imports...
public class Renderer {
public void init() {
Utils.loadResource("/vertex.vs"); // fails
}
}
// project-root/src/main/resources/vertex.vs
// vertex shader code...
问题是getResourceAsStream()调用返回null,因此以下依赖于有效结果的代码使用java.lang.NullPointerException崩溃。
我应该向getResourceAsStream()传递什么路径才能使它不返回null?
发布于 2019-05-21 13:20:36
假设目录结构如下:
|-- src
`-- test
|-- java
| `-- shaders
| `-- ShaderParser.java
`-- resources
`-- shaders
`-- fragmentShader.txt
从"ShaderParser.java“获取资源"fragmentShader.txt”的正确方法是:
Class clazz = Class.forName(TestUtils.class.getName());
InputStream in = clazz.getResourceAsStream("../../resources/shaders/fragmentShader.txt");
../
的意思是“向上遍历一个目录”。路径从src/test/java/shaders/
目录开始,因此我们使用../../
向上遍历src/test/
两次,然后添加路径resources/shaders/fragmentShader.txt
的其余部分。
重要的是要记住,在使用Class#getResourceAsStream()时,它使用类所在的包作为基目录。It ONLY使用相对路径,因为它试图使用该类的ClassLoader加载资源。如果提供了完全限定的路径或从项目根开始的路径,则将不起作用。
有关详细信息,请参阅documentation。
发布于 2019-05-25 16:54:08
我曾错误地认为Java有一个保留的目录(例如'resources'),它会首先在这个目录中加载文件。有点像python中的Flask。
但是,我现在了解到class.getResourceAsStream()函数要么采用相对路径(到当前“最低”级别的包),要么采用绝对路径(从项目的顶层根)。
此外,我还错误地认为我可以尝试从一个更高级别的包中进行相对路径加载。与在中一样,我在main.java.org.lwjgl.engine.Utils包中,但在查找文件main.resources.vertex.vs时,我可以从'main‘包开始搜索,并传递'resources/vertex.vs’或'resources/vertex.vs‘。我不知道这是否可能,但这感觉是错误的。
相反,解决方案是传递文件位置'/main/resources/vertex.vs‘。这将从project-root开始,并正确加载文件。
我仍然对lwjgl code的工作原理感到困惑,但我认为classPath可能被设置为“main”,所以传递一个绝对路径就可以了。
https://stackoverflow.com/questions/56230865
复制