为什么getResourceAsStream返回null? [英] Why is getResourceAsStream returning null?

查看:103
本文介绍了为什么getResourceAsStream返回null?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的罐子中有一个要加载的图像,但是getResourceAsStream()始终返回null.

目录结构:

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

Content.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");
    }

}

StackTrace:

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().我已经尝试过在前缀上加上或不带前缀"/",所以我全都没主意,而Google也无济于事.另外,我在定义前缀"时似乎很尴尬,因此,如果有更好的方法,如果有人向我展示了方法,我将非常高兴.

谢谢.

解决方案

在调用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");,因为它始终可以在您调用的位置以及您所处的类加载器中运行,并且显式可以在哪里找到要查找的内容.

I have an image inside my jar which I am trying to load, but getResourceAsStream() always returns null.

Directory structure:

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

Content.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");
    }

}

StackTrace:

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)

I have no idea why the classloader can't find the image. I have looked in the compiled jar and the file is there, and opens fine in paint so the file is OK. I have tried various ClassLoader variations, including getSystemClassLoader(), getClassLoader(), and Content.class.getClassLoader(); and also getResourceAsStream(path) instead of getResource(path).openStream(). I have tried with and without the leading '/' on the prefix, so I'm all out of ideas and Google isn't helping. Also, it seems like what I'm doing to define 'prefix' is very awkward and so if there is a better way I would be glad if someone showed me how.

Thanks.

解决方案

It is all about relative vs absolute packages when calling getResourceAsStream(), you looking for something relative to whatever package Content is at as the root.

there are no "directories" on the classpath, especially inside .jar files, only packages

The best thing to use is Thread.currentThread().getContextClassloader().getResourceAsStream() with a fully qualified package without the leading /.

The reason this is best is because inside of application containers, they usually have multiple classloaders and this way you don't have to care which one your resource is loaded from.

In your case:

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

If you still get an error with this approach your .jar isn't built like you think it is or if you are getting this from inside an IDE you probably aren't copying the contents resource/generic/ into the classpath.

Personally I always use the form:

Thread.currentThread().getContextClassLoader().getResourceAsStream("path/to/resource/file.ext"); as it always works from where ever you call it and whatever classloader you are in, and it is explicit about where it is looking to find what it is looking for.

这篇关于为什么getResourceAsStream返回null?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆