I’m using a custom method to get pictures from the resources/
folder. The hardcoded path works well when programming during production (src/main/resources/
). However when delivering, I would need to make this path relative to the .jar root. So I made this.
public static Image getImageFromFile(String file) { Image image = null; try { String path = FileUtils.class.getClassLoader().getResource(file).toExternalForm(); System.out.println(path); File pathToFile = new File(path); image = ImageIO.read(pathToFile); } catch (IOException ex) {ex.printStackTrace();} return image; }
file:/C:/Users/Hugo/Desktop/Hugo/Java%20Workspace/ClashBot/bin/main/icons/level-label.png javax.imageio.IIOException: Can't read input file! at javax.imageio.ImageIO.read(Unknown Source) at com.lycoon.clashbot.utils.FileUtils.getImageFromFile(FileUtils.java:55)
The printed path is valid and points to the corresponding picture. However, the program raises an IOException.
Why can’t it find the file?
Advertisement
Answer
You’re jumping through way too many hoops. It’s quite simple:
FileUtils.class.getResource("path.png"); // -OR- try (var in = FileUtils.class.getResourceAsStream("path.png")) { // in is an inputstream. }
is all you need. Note that this means the path.png
file is searched for in the exact same place (and even same ‘subdir’) as where FileUtils lives. So if you have, say, a file on C:ProjectsHugoMyAppmyapp.jar
, and if you were to unzip that, inside you’d find com/foo/pkg/FileUtils.class
, then the string path.png
would look in that jar, and for com/foo/pkg/path.png
. In other words, AnyClass.class.getResource("AnyClass.class")
will let a class find its own class file. If you want to go from the ‘root’ of the jar, add a slash, i.e. FileUtils.class.getResource("/path.png")
looks in the same jar, and for /path.png
inside that jar.
getResource
returns a URL. getResourceAsStream
returns a stream (which you need to close; use try-with-resources as I did). Just about every resource-using API out there will take one of these two as input. For example, ImageIO does so; it even takes a URL so you can use either one:
var image = ImageIO.read(FileUtils.class.getResource("imgName + ".png"));
Yes. It’s a one-liner. This will load images straight from within a jar file!