Java ImageIO.read() 返回 null

Java ImageIO.read() returning null

我想在我的项目中读取图像(.png 文件),我希望它也能在 运行 可用的 .jar 文件中工作。所以我写了这段代码:

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: java.io.BufferedInputStream@15db9742
Exception in thread "main" java.lang.NullPointerException
    at test.Loader.load(Loader.java:21)
    at test.MainTest.main(MainTest.java:6)

我的 MainTest 除了 运行 这段代码什么都不做,所以我不会在这里包含它。

我已经测试过 InputStream 是否如您可能已经注意到的那样 null。因为它显然不是我文件的路径必须是正确的。我的问题是:为什么 ImageIO.read() 返回 null

https://docs.oracle.com/javase/8/docs/api/javax/imageio/ImageIO.html#read-javax.imageio.stream.ImageInputStream-

如果无法解码图像,

ImageIO.read(...) 可能 return 为 null。还要检查这种情况。

正如您在调用 ImageIO.read 之前在 InputStream 上读到的那样,函数可能无法正确解码图像。删除对 in.read() 的调用并测试调用结果。

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

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

当你从流中读取一个字节时,这个字节实际上是 "consumed" 并且不会被再次读取,因此 ImageIO 永远不会看到这个字节,导致文件格式 (PNG)不被认可。在这种情况下,ImageIO.read(..) 将 return 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() 方法进行测试)。