如何获取.jar 资源路径?

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: Can't read input file!
    at javax.imageio.ImageIO.read(Unknown Source)
    at com.lycoon.clashbot.utils.FileUtils.getImageFromFile(FileUtils.java:55)

打印的路径有效,指向对应的图片。但是,该程序引发 IOException。

为什么找不到文件?

您可以尝试使用稍微不同的调用方式,例如:

java.net.URL fileUrl = Thread.currentThread().getContextClassLoader().getResource(file);
String filePath = URLDecoder.decode(fileUrl.getPath(), "UTF-8");
image = ImageIO.read(filePath);

你跳过了太多的障碍。很简单:

FileUtils.class.getResource("path.png");
// -OR-

try (var in = FileUtils.class.getResourceAsStream("path.png")) {
    // in is an inputstream.
}

就是你所需要的。请注意,这意味着 path.png 文件在与 FileUtils 所在的位置完全相同(甚至相同 'subdir')的位置进行搜索。因此,如果你有一个文件 C:\Projects\Hugo\MyApp\myapp.jar,如果你要解压缩它,你会在里面找到 com/foo/pkg/FileUtils.class,然后字符串 path.png 会在那个 jar 中查找,并且对于 com/foo/pkg/path.png。换句话说,AnyClass.class.getResource("AnyClass.class") 会让 class 找到它自己的 class 文件。如果你想从 jar 的 'root' 开始,添加一个斜杠,即 FileUtils.class.getResource("/path.png") 在同一个 jar 中查找,对于 /path.png 在那个 jar 中查找。

getResourcereturns一个URL。 getResourceAsStream returns 一个流(你需要关闭它;像我一样使用 try-with-resources)。几乎每个 resource-using API 都会将这两个中的一个作为输入。例如,ImageIO 就是这样做的;它甚至需要一个 URL 所以你可以使用其中一个:

var image = ImageIO.read(FileUtils.class.getResource("imgName + ".png"));

是的。这是一个one-liner。这将直接从 jar 文件中加载图像!