使用 getClass().getResource() 加载资源

Posted

技术标签:

【中文标题】使用 getClass().getResource() 加载资源【英文标题】:Loading resources using getClass().getResource() 【发布时间】:2011-01-21 12:57:42 【问题描述】:

我正在尝试加载图像以在我的应用程序中用作图标。根据这个tutorial的合适方法是:

protected ImageIcon createImageIcon(String path, String description) 

    java.net.URL imgURL = getClass().getResource(path);
    if (imgURL != null) 
        return new ImageIcon(imgURL, description);
     else 
        System.err.println("Couldn't find file: " + path);
        return null;
    

所以,我放置了文件的位置,并将其作为参数传递给该函数。这不起作用,即 imgURL 为空。当我尝试通过显式传递路径来创建 ImageIcon 时:

ImageIcon icon  = new ImageIcon(path,"My Icon Image");

效果很好!因此应用程序可以从明确定义的路径中获取图像,但不会使用 getResources() 来获取图像。在这两种情况下,路径变量的值是相同的。为什么它不起作用?类加载器如何找到资源?

谢谢。

【问题讨论】:

您使用的是 IDE 吗? IDE 是否设置为将资源复制到类编译到的任何位置? 图像相对于类和项目根目录的位置在哪里? 是的,我使用的是 Eclipse,它没有设置为复制资源。已经解决了。该类位于 root/bin//MyClass,图像位于 root/resources/images/myImage.gif 感谢您的回复。 【参考方案1】:

getClass().getResource(path) 从类路径加载资源,而不是从文件系统路径加载。

【讨论】:

哈哈!我假设他有类路径而不是文件路径。我会更正我的答案。【参考方案2】:

您可以请求这种格式的路径:

/package/path/to/the/resource.ext

即使是在内存中创建类的字节也是这样找到的:

my.Class -> /my/Class.class

getResource 会为您提供一个 URL,该 URL 可用于检索 InputStream

但是...我建议直接使用具有相同参数的getClass().getResourceAsStream(...),因为它直接返回 InputStream 并且不必担心创建必须知道如何创建的(可能很复杂)URL 对象输入流。

简而言之:尝试使用getResourceAsStreamImageIcon 的一些构造函数,它使用InputStream 作为参数。

类加载器

如果您的应用有很多类加载器,请小心。如果您有一个简单的独立应用程序(没有服务器或复杂的东西),您不必担心。如果ImageIcon 能够找到它,我认为情况并非如此。

编辑:类路径

getResource——正如 mattb 所说——用于从类路径(从你的 .jar 或类路径目录)加载资源。如果您正在捆绑一个应用程序,最好将其全部包含在内,因此您可以将图标文件包含在应用程序的 jar 中并通过这种方式获取。

【讨论】:

【参考方案3】:

作为一个菜鸟,我对此感到困惑,直到我意识到所谓的“路径”是路径 相对 到 MyClass。 文件系统中的文件,而不是 MyClass.java 文件。我的 IDE 将资源(如 xx.jpg、xx.xml)复制到 MyClass.class 的本地目录。例如,在名为“target/classes/pkg”的 pkg 目录中。对于不同的 IDE,类文件的位置可能会有所不同,具体取决于应用程序的构建方式。您应该首先探索文件系统并找到MyClass.class 文件和您要提取的相关资源的复制位置。然后确定相对于 MyClass.class 文件的路径,并将其写入为带有“点”和“斜线”的字符串值。

例如,以下是我如何使 app1.fxml 文件可用于我的 javafx 应用程序,其中相关的“MyClass.class”隐含为“Main.class”。 Main.java 文件是包含这行资源调用代码的位置。在我的具体情况下,资源被复制到与封闭包文件夹相同级别的位置。即:/target/classes/pkg/Main.class 和 /target/classes/app1.fxml。所以解释......相对引用“../app1.fxml”是“从Main.class开始,上一级目录,现在你可以看到资源”。

FXMLLoader loader = new FXMLLoader();
        loader.setLocation(getClass().getResource("../app1.fxml"));

请注意,在此相对路径字符串“../app1.fxml”中,前两个点引用包含 Main.class 的目录和单个“.”表示要遵循的文件扩展名。在这些细节成为第二天性之后,您会忘记为什么会令人困惑。

【讨论】:

【参考方案4】:

通过示例获取资源:

package szb.testGetResource;
public class TestGetResource 
    private void testIt() 
        System.out.println("test1: "+TestGetResource.class.getResource("test.css"));
        System.out.println("test2: "+getClass().getResource("test.css"));
    
    public static void main(String[] args) 
        new TestGetResource().testIt();
    

输出:

test1: file:/home/szb/projects/test/bin/szb/testGetResource/test.css
test2: file:/home/szb/projects/test/bin/szb/testGetResource/test.css

【讨论】:

我发现您的回答最有帮助。谢谢:)【参考方案5】:

getResourceAsStream() 查看资源文件夹的内部。所以文件应该放在定义的资源文件夹中 即如果文件位于 /src/main/resources/properties --> 那么路径应该是 /properties/yourFilename。

getClass.getResourceAsStream(/properties/yourFilename)

【讨论】:

以上是关于使用 getClass().getResource() 加载资源的主要内容,如果未能解决你的问题,请参考以下文章

IntelliJ IDEA - getClass().getResource("...") 返回 null

getClass().getResource() 异常?

ImageIO.read(getClass().getResource("imagepath")) 中 getclass() 的实际目的是啥 [重复]

this.getClass().getClassLoader().getResourceAsStream()和this.getClass().getClassLoader().getResource(

zbb20170604 java file 路径 this.getClass().getResource(String) 路径问题

this.getClass().getResource(String) 路径问题