【问题标题】:Why is getResourceAsStream returning null?为什么 getResourceAsStream 返回 null?
【发布时间】:2014-12-07 06:38:21
【问题描述】:

我的 jar 中有一个图像,我正在尝试加载它,但 getResourceAsStream() 总是返回 null。

目录结构:

com/thesimpzone/watch_pugs/watch_pugs/{all my class files}
META-INF/MANIFEST.MF
resources/generic/mouse.png

内容.java:

public abstract class Content {

    protected Map<String, BufferedImage> images = new HashMap<String, BufferedImage>();

    protected String prefix;

    public Content(String prefix){
        this.prefix = prefix;
    }

    protected void loadImage(String name){
        System.out.println(name);
        System.out.println(prefix);
        String path = (prefix + name);
        System.out.println(path);
        String identifier = name.substring(0, name.lastIndexOf("."));
        try{
            InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
            images.put(identifier, ImageIO.read(in));
        }catch(IOException | ClassCastException e){
            throw new RuntimeException("Image " + identifier + " at " + path + " could not be loaded.");
        }
    }
    [...]
}

GenericContent.java:

public class GenericContent extends Content {

    public GenericContent(){
        super("resources/generic/");
        this.loadContent();
    }

    @Override
    public void loadContent() {
        loadImage("mouse.png");
    }

}

堆栈跟踪:

mouse.png
resources/generic/
resources/generic/mouse.png
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: input == null!
    at javax.imageio.ImageIO.read(ImageIO.java:1348)
    at com.thesimpzone.watch_pugs.watch_pugs.content.Content.loadImage(Content.java:29)
    at com.thesimpzone.watch_pugs.watch_pugs.content.GenericContent.loadContent(GenericContent.java:17)
    at com.thesimpzone.watch_pugs.watch_pugs.content.GenericContent.<init>(GenericContent.java:12)
    at com.thesimpzone.watch_pugs.watch_pugs.Canvas.<init>(Canvas.java:45)
    at com.thesimpzone.watch_pugs.watch_pugs.Framework.<init>(Framework.java:75)
    at com.thesimpzone.watch_pugs.watch_pugs.Window.<init>(Window.java:50)
    at com.thesimpzone.watch_pugs.watch_pugs.Window.<init>(Window.java:26)
    at com.thesimpzone.watch_pugs.watch_pugs.Window$1.run(Window.java:60)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744)
    at java.awt.EventQueue.access$400(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:697)
    at java.awt.EventQueue$3.run(EventQueue.java:691)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:714)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

我不知道为什么类加载器找不到图像。我查看了编译后的 jar,文件在那里,并且在油漆中打开正常,所以文件没问题。我尝试了各种 ClassLoader 变体,包括 getSystemClassLoader()、getClassLoader() 和 Content.class.getClassLoader();还有 getResourceAsStream(path) 而不是 getResource(path).openStream()。我已经尝试过在前缀上使用和不使用前导“/”,所以我完全没有想法,谷歌也没有帮助。另外,我定义“前缀”的做法似乎很尴尬,所以如果有更好的方法,如果有人告诉我如何做,我会很高兴。

谢谢。

【问题讨论】:

  • 旁注:prefix 已经是String。没有必要在上面调用toString()
  • 哦,是的,那是从我尝试使用 char[] 时开始的,所以它可能是最终的。
  • 作为下次的建议,不要通过覆盖您的原始代码来编辑您的问题。它误导了答案。如果需要,通过添加您正在尝试的新代码和结果进行编辑。

标签: java getresource


【解决方案1】:

当调用getResourceAsStream() 时,这完全是关于相对包与绝对包,您正在寻找与Content 所在的包相关的东西作为根。

类路径中没有“目录”,尤其是在 .jar 文件中,只有包

最好使用Thread.currentThread().getContextClassloader().getResourceAsStream() 和一个完全限定的包没有领先的/

这是最好的原因是因为在应用程序容器内部,它们通常有多个类加载器,这样你就不必关心你的资源是从哪一个加载的。

在你的情况下:

Thread.currentThread().getContextClassloader().getResourceAsStream("resources/generic/mouse.png");

如果您在使用这种方法时仍然遇到错误,则您的 .jar 没有像您想象的那样构建,或者如果您是从 IDE 中获取的,您可能没有将内容 resource/generic/ 复制到类路径中。

就我个人而言,我总是使用这种形式:

Thread.currentThread().getContextClassLoader().getResourceAsStream("path/to/resource/file.ext"); 因为它总是在你调用它的地方和你所在的任何类加载器中工作,它明确知道它在哪里寻找它正在寻找的东西。

【讨论】:

  • 嗯仍然给出完全相同的错误(更新 OP 以显示当前代码)我也尝试使用文字而不是变量,但由于 InputStream 为空,它仍然显示完全相同的 IllegalArgumentException。跨度>
  • 那么您的 .jar 并没有像您想象的那样构建,如果您是从 IDE 中获取它,您可能不会将 resource/generic 复制到类路径中。那么这是您的配置问题。
  • 我的目录结构取自提取导出的.jar,所以图像就在那里。
  • 嗯,好的,我在 Eclipse 中得到了错误,但显然当我现在运行导出的(独立)jar 时它加载得很好?
【解决方案2】:

试试 Content.class.getClassLoader().getResourceAsStream(path);

【讨论】:

    猜你喜欢
    • 2015-02-19
    • 1970-01-01
    • 2011-07-11
    • 2013-10-02
    • 2013-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多