简体   繁体   English

ImageIO 找不到文件

[英]ImageIO Cannot Find File

I'm writing a program involving graphical interface and I'm using ImageIO to read an image into a BufferedImage (the variable starImg ) in the code below:我正在编写一个涉及图形界面的程序,并且在下面的代码中使用ImageIO将图像读入BufferedImage (变量starImg ):

public Star() {
    super();
    if (starImg == null) {
        try {
            starImg = ImageIO.read(new File("star.png"));
        } catch (IOException e) {
            System.out.println("There was an issue reading the file: " + e);
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

Except the code always ends up outputting the IO file not found exception message, even though it shouldn't.除了代码总是输出 IO 文件未找到异常消息,即使它不应该。 My star.png file is in the same folder as my code (ran using Eclipse), I've made sure that it's a png and not a jpg, and tried other things like changing File to FileInputStream, so I can't seem to figure out why this image cannot be read.我的 star.png 文件与我的代码位于同一文件夹中(使用 Eclipse 运行),我确保它是 png 而不是 jpg,并尝试了其他操作,例如将 File 更改为 FileInputStream,所以我似乎无法弄清楚为什么无法读取此图像。 Maybe it has something to do with the fact that I'm using Eclipse, although I find this unlikely.也许这与我使用 Eclipse 的事实有关,尽管我觉得这不太可能。 I've looked at other answers relating to the same issue, but the solutions that solved their problems haven't solved mine.我查看了与同一问题相关的其他答案,但解决他们问题的解决方案并没有解决我的问题。

If someone could point out the bug in my code, that would be greatly appreciated.如果有人能指出我的代码中的错误,那将不胜感激。

My star.png file is in the same folder as my code (ran using Eclipse)我的 star.png 文件与我的代码在同一个文件夹中(使用 Eclipse 运行)

Well, there is your problem.嗯,有你的问题。

new File("star.png") will look in the process current working directory. new File("star.png")将在进程当前工作目录中查找。

Where is that?哪里是? Who knows!谁知道! - it's up to the user; - 由用户决定; where-ever the app was started from.应用程序是从哪里开始的。 Thus, this is broken as a concept: There is absolutely no guarantee that it is the right place.因此,这作为一个概念被打破了:绝对不能保证它是正确的地方。

It gets worse - java apps are shipped as jars or jmods, and the files they need are enclosed within.情况变得更糟 - java 应用程序以 jars 或 jmods 的形式提供,它们需要的文件包含在其中。 Entries in jar files or jmod files are not files . jar 文件或 jmod 文件中的条目不是文件 new File() cannot possibly read these . new File()不可能读取这些.

The conclusion is that this process (make a file object, pass it to ImageIO.read) cannot work for resources.结论是这个过程(制作一个文件object,将它传递给ImageIO.read)不能为资源工作

The solution is to ask the java classloading system to give you resources from where-ever the VM is loading classes from.解决方案是要求 java 类加载系统为您提供来自 VM 加载类的任何位置的资源。 If that's from disk, great, get em from there.如果那是来自磁盘,那太好了,从那里获取它们。 If that's from within a jar or jmod file, cool, get em from there.如果那来自 jar 或 jmod 文件,很酷,从那里获取 em。

This is how you do that:这就是你这样做的方式:

URL url = Star.class.getResource("star.png");

// - OR -

try (InputStream in = Star.class.getResourceAsStream("star.png")) {
   // use in here
}

The first one is useful whenever you have an API that accepts URL objects.当您有一个接受 URL 对象的 API 时,第一个非常有用。 I'm pretty sure ImageIO.read() is such an API.我很确定 ImageIO.read() 就是这样一个 API。

The second is useful for APIs that accept InputStreams.第二个对于接受 InputStreams 的 API 很有用。 ImageIO.read also does that - if both are available, the URL based one is simpler (no need for a try-with-resources in that case). ImageIO.read 也这样做 - 如果两者都可用,则基于 URL 的更简单(在这种情况下不需要尝试资源)。

Note that this will look in the same place Star.class ended up, so in Star's 'package', so to speak.请注意,这将在同一个地方Star.class结束,所以可以说是在 Star 的“包”中。 If you'd rather go from the 'root' folder (the root of the jar, for example), use eg "/img/star.png" instead;如果您更喜欢“根”文件夹(例如 jar 的根目录)中的 go,请改用"/img/star.png" this will look in a dir named 'img' for the file, and that dir must be in the 'root'.这将在一个名为“img”的目录中查找该文件,并且该目录必须位于“根目录”中。 So, if Star has package com.foo;所以,如果 Star 有package com.foo; at the top, there is some construct (jar file, jmod, etc) that has a com dir, which has a foo dir, which has a Star.class file.在顶部,有一些结构(jar 文件、jmod 等)有一个com目录,它有一个foo目录,它有一个Star.class文件。 With "/img/star.png" , there must be a dir named img , as sibling to the dir named com .使用"/img/star.png" ,必须有一个名为img的目录,作为名为com的目录的兄弟。

Eclipse will automatically copy non-java files in src folders over, as an analogy: It 'copies' java files over by compiling them, and it 'compiles' non-java files by just copying them over. Eclipse 将自动复制 src 文件夹中的非 java 文件,作为类比:它通过编译它们来“复制”java 文件,并通过仅复制它们来“编译”非 java 文件。 Hence, this works fine in eclipse, and also works fine with build systems (note that with maven, there is a dir structure to adhere to. sources go in src/main/java , non-java stuff goes in src/main/resources . Hence, this works fine in eclipse, and also works fine with build systems (note that with maven, there is a dir structure to adhere to. sources go in src/main/java , non-java stuff goes in src/main/resources .

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

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