【问题标题】:Trouble With Java getResourceAsStream, confusion with how Packages workJava getResourceAsStream 出现问题,对包的工作方式感到困惑
【发布时间】:2019-05-26 01:06:30
【问题描述】:

在高中短暂学习 Java 以通过 lwjgl git book 工作后,我正在重新审视 Java。使用函数“getResourceAsStream”来加载片段着色器/顶点着色器的地方让我有些不知所措。

我尝试了不同的方法,但徒劳地尝试调试/打印 JVM 正在搜索文件的位置,但我有点不知所措。我很困惑,但也希望了解为什么这段代码不能在我的机器上工作,以及如何让它工作(使用这种包/类加载方法)。

由于这些类都共享“主”类,我认为 JVM 会从那里开始搜索“资源”文件夹。但这似乎并非如此。

我确实认为这与包声明有关,但我理解得不够深入。

以下是相关文件和位置...我试图只包含我认为重要的内容。

// 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?

【问题讨论】:

    标签: java resources lwjgl


    【解决方案1】:

    假设如下目录结构:

    |-- 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() 时,它使用类所在的包作为基目录。它使用相对路径,因为它试图使用该类的ClassLoader 加载资源。如果提供完全限定路径或从项目根目录开始的路径,则将无法使用。

    更多信息请参考documentation

    【讨论】:

    • 在这种情况下,我不会尝试传递相对于当前包的文件路径,因为这些包是 java 类所在的,所以相对路径会令人讨厌。我添加了一个答案,解释了我在寻找什么,以及我找到的解决方案。
    【解决方案2】:

    我错误地认为 Java 有一个保留目录(例如“资源”),它会首先在其中加载文件。有点类似于 python 中的 Flask。

    但是,我现在明白 class.getResourceAsStream() 函数采用相对路径(到当前“最低”级别的包)或绝对路径(从项目的顶级根目录)。

    我还错误地认为我可以尝试从更高级别的包之一进行相对路径加载。如中,我在包 main.java.org.lwjgl.engine.Utils 中,但是在查找文件 main.resources.vertex.vs 时,我可以从“主”包开始搜索并传递“资源/ vertex.vs' 或 'resources/vertex.vs'。我不知道这是否可能,但感觉是错误的。

    相反,解决方案是传递文件位置“/main/resources/vertex.vs”。这将从项目根目录开始,并正确加载文件。

    我仍然对lwjgl code 的工作方式感到困惑,但我发现可能将 classPath 设置为“main”,因此传递绝对路径可能会起作用。

    【讨论】:

      猜你喜欢
      • 2012-08-24
      • 2019-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-10
      • 1970-01-01
      • 1970-01-01
      • 2019-08-31
      相关资源
      最近更新 更多