2016-02-16 124 views
1

我想在我的项目中读取图像(.png文件),并且我希望它在可运行的.jar文件中工作。所以我写了这一小段代码:Java ImageIO.read()返回null

try { 
    InputStream in; 
    in = Loader.class.getClassLoader().getResourceAsStream("buttons.png"); 

    System.out.println(in.read() + ", Reader: " + in);   

    BufferedImage img = ImageIO.read(in); 

    System.out.println(img.getHeight()); 

    in.close(); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 

当我运行它,我得到以下的输出:

137, Reader: [email protected] 
Exception in thread "main" java.lang.NullPointerException 
    at test.Loader.load(Loader.java:21) 
    at test.MainTest.main(MainTest.java:6) 

MainTest没有什么,但运行此代码,所以我将不包括它这里。

我已经测试过,如果InputStreamnull,您可能已经注意到了。因为它显然不是我的文件的路径必须是正确的。我的问题是:为什么ImageIO.read()返回null?如果它是无法解码图像

+0

检查'buttons.png'是否位于Loader类路径的根目录下。区分大小写,使用7zip,WinZip或类似文件检查.jar文件。 –

+1

当资源无法找到时,getResource(AsStream)将返回null – MadProgrammer

回答

3

与您的代码的问题是,它传递给ImageIO.read(..)之前,从in读取的行(您正在阅读的第一个字节):

System.out.println(in.read() + ", Reader: " + in); 

当你从流读取一个字节,该字节实际上是“消耗”并且不会被再次读取,因此ImageIO将永远不会看到该字节,导致文件格式(PNG)不被识别。在这种情况下,ImageIO.read(..)将返回null

只要删除该行,并且您的代码应该可以正常工作。

该文件似乎存在为in不是null。并且您打印的值137实际上是PNG signature的第一个字节,表示该文件很好,并且正确地包含在您的JAR中。


如果你真的需要传递给ImageIO之前窥视到流中的字节数,你可以这样做:

in.mark(256); // allows you to read up to 256 bytes before calling reset() 
System.out.println(in.read() + ", Reader: " + in); // or whatever you like to do 
in.reset(); // "rewind" to beginning of stream (previous mark) 

只是要小心,因为不是所有的流支持mark()/reset()方法(你可以使用boolean markSupported()方法进行测试)。

+0

绝对正确。我现在也是这样做的:D。但非常感谢你的帮助和详细的解释:) – Deadbyrd12

1

正如您在拨打ImageIO.read之前已阅读InputStream,可能会发生该功能无法正确解码图像。删除对in.read()的呼叫,并测试呼叫的结果。