简体   繁体   English

在.jar文件中加载图像时出现NullPointerException

[英]NullPointerException when loading images in .jar-file

I am developing a java project in eclipse. 我正在eclipse中开发一个java项目。 In order to distribute the program I have created a runnable .jar-file via the export-function in eclipse. 为了分发程序,我通过eclipse中的export-function创建了一个可运行的.jar文件。

In my program a load several images that are stored in a folder called 'tableImages'. 在我的程序中,加载了几个存储在名为“tableImages”的文件夹中的图像。 I load the images via the ClassLoader (you'll find the code snippets below). 我通过ClassLoader加载图像(你会在下面找到代码片段)。 The problem is the following: When executing the program from the .jar-file, it throws a NullPointerException when loading one of the .png-files in the above mentioned folder. 问题如下:从.jar文件执行程序时,在上面提到的文件夹中加载一个.png文件时会抛出NullPointerException。 Now the funny thing is, that some of the .png-files in the exact same folder are loaded correctly, meaning they don't cause a NullPointerException. 现在有趣的是,完全相同的文件夹中的一些.png文件被正确加载,这意味着它们不会导致NullPointerException。

I checked the content of the .jar using the jar tf command. 我使用jar tf命令检查了.jar的内容。 The image that apparently cannot be loaded, was packed into the jar. 显然无法加载的图像被装入罐子里。 So what is causing this NullPointerException and how can I solve it? 是什么导致了这个NullPointerException以及如何解决它?

Here is the class with which I draw images to my swing-frame. 这是我用我的秋千框架绘制图像的类。

import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import java.net.*;

public class LoadBackgroundImage extends Component {

    private static final long serialVersionUID = 1L;

    BufferedImage img;

    public void paint(Graphics g){
        g.drawImage(img, 0, 0, null);
    }

    public LoadBackgroundImage(String image){
        URL url = ClassLoader.getSystemResource(image);
        try{
            img = ImageIO.read(url);
            this.setSize(img.getWidth(), img.getHeight());
        }catch(IOException e){
            System.err.println(e.getMessage());
        }
    }

    public Dimension getPreferredSize(){
        if(img == null){
            return new Dimension(100, 100);
        }else{
            return new Dimension(img.getWidth(null), img.getHeight(null));
        }
    }

    public BufferedImage getImage(){
          return img;
         }

}

Thank you very much for your help! 非常感谢您的帮助!

URL url = ClassLoader.getSystemResource(image);

This URL translates to absolute path in the file system which will be an invalid path for a file within jar. 此URL转换为文件系统中的绝对路径,该路径将是jar中文件的无效路径。 For example, if you have a file called foo.png under bar.jar the URL will be /path_to_current_dir/bar.jar/!foo.png which is invalid. 例如,如果bar.jar下有一个名为foo.png的文件,则URL为/path_to_current_dir/bar.jar/!foo.png无效。 Instead you can read the file as a stream: 相反,您可以将文件作为流读取:

InputStream is = getClass().getClassLoader().getResourceAsStream(image);
ImageIO.read(is);

Assuming that the file is indeed in the .jar package, the reason is most likely that entries in .jar-files are loaded in a case sensitive matter so that foo.png is not the same as Foo.png . 假设该文件确实是在的.jar包,原因是最有可能的是,在的.jar档案条目的情况下,敏感的问题被加载,这样foo.png一样的Foo.png When you load from regular files the behavior depends on the file system so on Windows and Mac foo.png and Foo.png will denote the same file(!). 从常规文件加载时,行为取决于文件系统,因此在Windows和Mac上, foo.pngFoo.png将表示相同的文件(!)。

You can use a URL, I just tried it myself and it works perfectly, getting the png files from within the jar: 你可以使用一个URL,我只是自己尝试过,它运行得很好,从jar中获取png文件:

Here's the code I used: 这是我使用的代码:

public static ImageIcon getIcon(String path)
    {
        String imageFile = "";

        if(path.equals(""))
            imageFile = "/Images/Icon.png";
        else
            imageFile = path;

        URL source = Messages.class.getResource(imageFile);
        if(source != null)
        {
            ImageIcon imageIcon = new ImageIcon(source);
            return imageIcon;
        }
        return null;
    }

Then I add it directly to a JLabel, worked like a charm, and I also moved the jar file around and renamed the imagefiles outside of the jar, so I'm sure. 然后我将它直接添加到JLabel,像魅力一样工作,我还移动了jar文件并将jar文件重命名为jar,所以我确定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM