如何获取Java JAR文件中的资源路径

问题

我试图找到资源的路径,但我没有运气。

这有效(在IDE和JAR中)但这样我无法获得文件的路径,只有文件内容:

ClassLoader classLoader = getClass().getClassLoader();
PrintInputStream(classLoader.getResourceAsStream("config/netclient.p"));

如果我这样做:

ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("config/netclient.p").getFile());

其结果是:java.io.FileNotFoundException: file:/path/to/jarfile/bot.jar!/config/netclient.p (No such file or directory)

有没有办法获得资源文件的路径?


#1 热门回答(65 赞)

这是故意的。 "文件"的内容可能无法作为文件提供。请记住,你正在处理可能属于JAR文件或其他类型资源的类和资源。类加载器不必为资源提供文件句柄,例如,jar文件可能尚未扩展到文件系统中的单个文件中。

如果java.io.File绝对必要,可以通过将流复制到临时文件并执行相同的操作来完成获取java.io.File所能做的任何事情。


#2 热门回答(41 赞)

加载资源时,请确保注意到以下两者之间的区别:

getClass().getClassLoader().getResource("com/myorg/foo.jpg") //relative path

getClass().getResource("/com/myorg/foo.jpg")); //note the slash at the beginning

我想,这种混乱在加载资源时会导致大多数问题。

此外,当你加载图像时,它更容易使用getResourceAsStream()

BufferedImage image = ImageIO.read(getClass().getResourceAsStream("/com/myorg/foo.jpg"));

当你真的必须从JAR存档加载(非图像)文件时,你可以尝试这样做:

File file = null;
    String resource = "/com/myorg/foo.xml";
    URL res = getClass().getResource(resource);
    if (res.toString().startsWith("jar:")) {
        try {
            InputStream input = getClass().getResourceAsStream(resource);
            file = File.createTempFile("tempfile", ".tmp");
            OutputStream out = new FileOutputStream(file);
            int read;
            byte[] bytes = new byte[1024];

            while ((read = input.read(bytes)) != -1) {
                out.write(bytes, 0, read);
            }
            file.deleteOnExit();
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
    } else {
        //this will probably work in your IDE, but not from a JAR
        file = new File(res.getFile());
    }

    if (file != null && !file.exists()) {
        throw new RuntimeException("Error: File " + file + " not found!");
    }

#3 热门回答(18 赞)

一行答案是 -

String path = this.getClass().getClassLoader().getResource(<resourceFileName>).toExternalForm()

基本上getResource方法给出了URL。在此URL中,你可以通过调用toExternalForm()来提取路径

参考文献:

getResource(),toExternalForm()