BufferedImage 在运行时为 Null

BufferedImage are Null in runtime

我在 运行 时遇到 BufferedImage 问题。我正在加载 .png,但 BufferedImage 为空。我没有得到 IOException,而是 NullPointerException。对我来说最大的问题是,当我 运行 在 netbeans 中使用相同的代码时,他工作正常...

我的密码是

public Image loadImage() throws IOException {
    BufferedImage bufferedImage = ImageIO.read(new File(ApplicationProperties.getPath() + "\.wimdesktop\image.png"));
    return SwingFXUtils.toFXImage(bufferedImage, null);
}

ApplicationProperties.getPath() 是静态的,不会在 运行 时间内改变。 如果我分开 BufferedImage 的声明并尝试 file.exists() 我会得到一个真实的结果

嗯,read the docs。当然,这是一种奇怪的行为,但是文档为您详细说明了这一点:

Returns a BufferedImage as the result of decoding a supplied File with an ImageReader chosen automatically from among those currently registered. The File is wrapped in an ImageInputStream. If no registered ImageReader claims to be able to read the resulting stream, null is returned.

(我加了亮点)。换句话说,这是故意的行为。

这个方法不好,你不应该调用它。呼叫其他人之一,收回一些控制权。 通常,此类图像与您的 class 文件一样静态:您在创建此程序时确定这些图像应该是什么,而您的用户并不打算制作它们,编辑它们,或以其他方式对其产生任何影响。因此,将这些图像存储在与 'store' 和 class 文件相同的位置是有意义的:一起存储在 jar 或 jmod 中。

您可以要求 java 从读取 class 文件的相同位置读取内容。我认为您应该改用该机制。您需要一个采用 InputStreamURL 的方法。幸运的是,两者都有 read 方法的重载。因此:

  • 如果你例如有一个 java 文件 MyApp.java,它以 package com.foo; 开头,然后你最终得到一个包含条目 com/foo/MyApp.class 的 jar 文件;如果你 运行 jar tvf myapp.jar.
  • 你可以看到这个
  • 现在确保图像在同一个 jar 中,可以在 com/foo 的(子目录)中,也可以在 jar 的根目录中,由您选择。假设你在那个罐子里有 com/foo/img/image.png

然后,从中制作一个 BufferedImage:

BufferedImage img = ImageIO.read(MyApp.class.getResource("img/image.png"));
return SwingFXUtils.toFXImage(img, null);

如果您出于某种奇怪的原因必须离开文件,请控制该过程以获得非愚蠢的错误处理(不幸的是,接受文件的 read 方法被认为是愚蠢的错误处理,所以你不需要那个):

try (FileInputStream in = new FileInputStream(new File(...))) {
   BufferedImage img = ImageIO.read(in);
}

这样,如果 img 现在为空,您就知道该文件很可能被读取得很好,但它要么根本不是有效图像,要么其格式 java 无法读取(例如,我认为 java 不能保证读取除 png 和 jpg 之外的任何内容。所以它可能在 HEIF/HEVC、TIFF、BMP 等中 - 东西 java据我所知将无法阅读。

对比您所做的,也可能是文件不存在或您的 java 进程没有文件的读取权限。