Java 无法读取jar文件中的图像

Java 无法读取jar文件中的图像,java,jar,nullpointerexception,embedded-resource,Java,Jar,Nullpointerexception,Embedded Resource,当我构建一个jar文件并运行它时,由于找不到imageicon,它会显示一个空指针异常 new ImageIcon(getClass().getClassLoader().getResource("icons/exit.png"))); 这就是我在运行jar文件时得到的错误 Exception in thread "main" java.lang.NullPointerException at javax.swing.ImageIcon.<init>(Unknown

当我构建一个jar文件并运行它时,由于找不到imageicon,它会显示一个空指针异常

new ImageIcon(getClass().getClassLoader().getResource("icons/exit.png")));
这就是我在运行jar文件时得到的错误

Exception in thread "main" java.lang.NullPointerException
        at javax.swing.ImageIcon.<init>(Unknown Source)
        at mediaplayer.MediaPlayer.buildtoolbar(MediaPlayer.java:130)
        at mediaplayer.MediaPlayer.<init>(MediaPlayer.java:81)
        at mediaplayer.MediaPlayer.main(MediaPlayer.java:464)

在jar文件实际上是如何构建的问题中,缺少了一些信息,但是使用了以下目录布局

├── bin
│   ├── com
│   │   └── example
│   │       └── ImageIconTest.class
│   └── icons
│       └── exit.png
└── src
    ├── MANIFEST.MF
    └── com
        └── example
            └── ImageIconTest.java
以及
ImageIconTest.java

package com.example;
import javax.swing.ImageIcon;

public class ImageIconTest {
   public void run() {
      ImageIcon ii = new ImageIcon(getClass().getClassLoader().getResource("icons/exit.png"));
      System.out.println(ii);
   }
   public static void main(String[] args) {
      ImageIconTest app = new ImageIconTest();
      app.run();
   }
}
您可以使用从文件系统正确运行示例

$ java -classpath bin com.example.ImageIconTest
使用包含以下内容的MANIFEST.MF文件:

Manifest-Version: 1.0
Main-Class: com.example.ImageIconTest
您可以将其打包到可执行的jar文件中,并从jar文件运行它:

$ jar cvfm app.jar src/MANIFEST.MF -C bin .
$ java -jar app.jar
这两种方法都可以正常工作,重要的细节是确保图标目录包含在jar文件的正确位置

列出jar文件内容时,应如下所示:

  0 Tue Nov 06 12:27:56 CET 2012 META-INF/
107 Tue Nov 06 12:27:56 CET 2012 META-INF/MANIFEST.MF
  0 Tue Nov 06 12:27:56 CET 2012 com/
  0 Tue Nov 06 12:27:56 CET 2012 com/example/
950 Tue Nov 06 12:27:56 CET 2012 com/example/ImageIconTest.class
  0 Tue Nov 06 12:00:36 CET 2012 icons/
873 Tue Nov 06 12:00:36 CET 2012 icons/exit.png
注意图标目录的位置。

此代码运行良好:

ClassLoader cl = getClass().getClassLoader();
InputStream stream = cl.getResourceAsStream( "hpms/study/Starbucks.jpg" );
if( stream == null ) System.err.println( "resource not found" );
BufferedImage image = ImageIO.read( stream );
ImageIcon icon = new ImageIcon( image );

当包
MediaPlayer
中的
MediaPlayer
调用位于
“icons/exit.png”
的嵌入式资源时,会发生异常。这将解决以下问题:

mediaplayer/icons/exit.png
我猜这不是路径,实际上是


这就是为什么
字符串
必须是
“/icons/exit.png”
-请注意
/
前缀。

字符串前面的
/
通知类加载器我们希望它搜索 资源来自类路径的根,而不是从中调用它的类的包。

比每个人都多。 我找到了答案

button = new JButton(new ImageIcon(getClass().getResource("/icons/playlist.png")));
我删除了ClassLoader()并成功了,但我不知道为什么。
有人能给我解释一下这背后的原理吗?

试试ClassLoader.class.getResource()。图像是否打包到JAR中?您应该以zip文件的形式打开JAR文件,以确保图标在那里。是的,图像包含在JAR文件中,我用winrar-1“研究不足”检查了它,几乎可以肯定的是,我在NetBeans的帮助下构建了jar文件,其中包括manifest文件,并正确设置了类路径。仍然无法使用命令行执行jar文件。@Haxor这不是很有帮助。jar文件中的文件结构是否与Andreas在回答中指定的相同,特别是其中的bin部分?您的清单可能很好,因为您的代码似乎在执行。@Thor84no right-但请注意,“bin”目录并不是jar文件的一部分。我已经用jar文件的结构更新了我的答案。@Haxor您是在使用某种特殊类型的类加载器,还是其他可能改变类加载行为的框架?或者这是“纯Java”@Andreas我在使用JMF(Java媒体框架)时,它能改变行为吗?当我使用/icons/exit.png时,它在netbeans和执行jar文件时也会给我同样的错误。。这是一个棘手的问题。可能是缓存旧罐子吗?如果它是小程序或使用JavaWebStart部署,则可能会出现这种情况。顺便说一句,为什么
Thumbs.db
在Jar中,为什么它和两个图像位于Jar中的两个位置?我倾向于删除Jar根目录下的
.db
文件和两个图像。它们似乎是多余的,而且(虽然这不应该是一个问题)可能会混淆类装入器。@AndrewThompson注意到一点。我想您的示例将与
Class.getResource()
一起使用,但与
ClassLoader.getResource()
一起使用应该不会有什么区别@Haxor您可以尝试使用`getClass().getResource(“/icons/exit.png”)?这应该和你正在尝试的是一样的。我刚刚尝试了一个前导斜杠,但失败了。我发现了一条解释它的帖子:@Andreas我不确定是否要删除我的答案。我认为最好暂时离开,这样OP就有机会看到并关注你的链接。谢谢你提醒我!:)我认为这一理论在下面的评论中的各个环节都有解释;)问题更像是为什么应用程序的行为与理论不同?我想我们需要更多信息:您使用哪个JDK/JRE和哪个版本来运行jar文件,您的命令行在运行jar文件时是什么样子的。@Andreas JDK 1.6.0 JRE 7这是javax.swing.ImageIcon上线程“main”java.lang.NullPointerException中的命令行输出
异常。(未知源)在mediaplayer.mediaplayer.buildtoolbar(mediaplayer.java:130)在mediaplayer.mediaplayer.(mediaplayer.java:81)在mediaplayer.mediaplayer.main(mediaplayer.java:464)
您用来启动应用程序的命令行是什么?像“java-classpath…”java-jar“C:\Documents and Settings\koi有ni-lagaega\My Documents\NetBeansProjects\MediaPlayer\dist\MediaPlayer.jar”“这应该可以用”。。。我有很多想法。需要对类加载器的细节进行更多的研究,并且可能需要一个新的、更关注的问题。
icons/exit.png
button = new JButton(new ImageIcon(getClass().getResource("/icons/playlist.png")));