英文:
How to get .jar resources path?
问题
我正在使用自定义方法从resources/
文件夹获取图片。在编写生产代码(src/main/resources/
)时,硬编码的路径效果良好。然而,在交付时,我需要使此路径相对于.jar根目录。所以我做了这个。
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: 无法读取输入文件!
at javax.imageio.ImageIO.read(Unknown Source)
at com.lycoon.clashbot.utils.FileUtils.getImageFromFile(FileUtils.java:55)
打印的路径是有效的,并指向相应的图片。然而,程序引发了一个IOException。
为什么它无法找到文件?
英文:
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.<br><br>
Why can't it find the file?
答案1
得分: 1
你正在跳过了太多步骤。实际上很简单:
FileUtils.class.getResource("path.png");
// -OR-
try (var in = FileUtils.class.getResourceAsStream("path.png")) {
// in是一个输入流。
}
这就是你需要的全部。请注意,这意味着path.png
文件在与FileUtils所在的位置(甚至是相同的“子目录”)中进行搜索。所以,假设你有一个文件在C:\Projects\Hugo\MyApp\myapp.jar
,如果你解压它,在内部你会找到com/foo/pkg/FileUtils.class
,那么字符串path.png
会在那个jar文件中寻找,以及在那个jar文件中寻找com/foo/pkg/path.png
。换句话说,AnyClass.class.getResource("AnyClass.class")
会让一个类找到它自己的类文件。如果你想从jar文件的“根”目录开始,加上斜杠,也就是FileUtils.class.getResource("/path.png")
会在同一个jar文件中寻找,在该jar文件中寻找/path.png
。
getResource
返回一个URL。getResourceAsStream
返回一个流(你需要关闭它;就像我做的那样使用try-with-resources)。几乎所有使用资源的API都会以这两者之一作为输入。例如,ImageIO就是这样做的;它甚至接受一个URL,因此你可以使用其中任何一个:
var image = ImageIO.read(FileUtils.class.getResource("imgName.png"));
是的。这只是一个一行代码。这将直接从jar文件中加载图像!
英文:
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:\Projects\Hugo\MyApp\myapp.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!
答案2
得分: -1
你可以尝试使用稍微不同的调用方式,就像这样:
java.net.URL fileUrl = Thread.currentThread().getContextClassLoader().getResource(file);
String filePath = URLDecoder.decode(fileUrl.getPath(), "UTF-8");
image = ImageIO.read(filePath);
英文:
You could try to use a slightly different call like this:
java.net.URL fileUrl = Thread.currentThread().getContextClassLoader().getResource(file);
String filePath = URLDecoder.decode(fileUrl.getPath(), "UTF-8");
image = ImageIO.read(filePath);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论