如何获取项目中 /resources 文件夹下文件的绝对路径

146
假设标准的maven设置已存在。
例如,在你的资源文件夹中有一个名为abc的文件。
在Java中,如何获取文件的绝对路径?

你想编写一个Maven插件吗?还是你想在程序执行时访问文件? - Gyro Gearless
相关:https://dev59.com/KGsz5IYBdhLWcg3wDzwA - Vadzim
根据情况,有三种解决方案的变体:https://dev59.com/DmQm5IYBdhLWcg3wxBVg#56327069 - Gangnus
7个回答

200

实际有效的正确方法:

URL resource = YourClass.class.getResource("abc");
Paths.get(resource.toURI()).toFile();

现在文件在classpath物理位置上无关紧要,只要资源实际上是一个文件而不是JAR条目,它就会被找到。

(显然的new File(resource.getPath())并不适用于所有路径!路径仍然是URL编码的!)


5
或者你可以直接这样做:new File(resource.toURI()).getAbsolutePath();(即我认为你不需要Path对象?) - Dan King
2
关于toURI()的好提示,这样可以避免路径中的空格变成%20! - Matthew Wise
38
谢谢!这个对我有些用处。但是我需要做一个修改:YourClass.class.getClassLoader().getResource("abc"); - yngwietiger
如果你愿意的话,你也可以使用 new File(YourClass.class.getResource("abc").toURI().getPath()) - Mike Rylander
9
我不明白为什么这么多人在没有加上起始斜杠的情况下使用.getResource("/abc"),请问这是如何生效的? - cahen
Kotlin:YourClass::class.java.classLoader.getResource("resource.txt") - ExactaBox

120
你可以使用ClassLoader.getResource方法来获取正确的资源。
URL res = getClass().getClassLoader().getResource("abc.txt");
File file = Paths.get(res.toURI()).toFile();
String absolutePath = file.getAbsolutePath();

或者

虽然这种方法并不总是有效的,但有一个更简单的解决方案——

您可以创建一个 File 对象并使用 getAbsolutePath 方法:

File file = new File("resources/abc.txt");
String absolutePath = file.getAbsolutePath();

11
这条建议的用处有限,因为它依赖于工作目录是maven根目录。即使如此,您也应该使用target/classes/abc.txt来引用文件,因为这是Maven在处理后放置资源文件的规范位置(例如,maven-resources插件可能已对abc.txt进行属性替换)。最好通过类路径中的getResource()方法来使用abc.txt。 - Gyro Gearless
4
如果最终用户将您的应用程序作为可执行JAR文件运行,那么根本就不会有物理文件。这是使用getResource()并根据所需执行操作打开输入流的另一个原因。 - Matthew Wise
7
可以将这个答案作为正确答案移除吗?@Karol S 在下面回答了 - 那应该是正确答案(因此出现了点赞数量不一致的情况)。 - DanGordon
3
错误答案。请参考@Karol的下面答案。 - bhathiya-perera
从技术上讲,我想它是可以工作的。我已经正确获取了根路径,但它没有指向我的模块实际资源文件夹的位置。 - David S

38

您需要指定以/开头的路径。

URL resource = YourClass.class.getResource("/abc");
Paths.get(resource.toURI()).toFile();

在我的情况下,它是一个 .png 文件,当我添加上述内容时,资源为空。请问如何处理位于资源文件夹中的 .png 或 .pdf 文件? - abc123

14
创建所需类的类加载器实例,然后您可以轻松访问文件或资源。 现在使用该类的getPath()方法访问路径。
 ClassLoader classLoader = getClass().getClassLoader();
 String path  = classLoader.getResource("chromedriver.exe").getPath();
 System.out.println(path);

5

在获取绝对路径时会遇到两个问题:

  1. 找到的位置不是源文件所在的位置,而是类所保存的位置。而资源文件夹几乎肯定位于项目的源文件夹中。
  2. 如果类在插件中运行或直接在工作区中的包中运行,则检索资源的相同函数将有所不同。

以下代码将为我们提供所有有用的路径:

    URL localPackage = this.getClass().getResource("");
    URL urlLoader = YourClassName.class.getProtectionDomain().getCodeSource().getLocation();
    String localDir = localPackage.getPath();
    String loaderDir = urlLoader.getPath();
    System.out.printf("loaderDir = %s\n localDir = %s\n", loaderDir, localDir);

这里研究了用于本地化资源文件夹的两个函数。对于class,可以静态或动态获取。


如果项目不在插件中,在 JUnit 中运行代码将会输出:

loaderDir = /C:.../ws/source.dir/target/test-classes/
 localDir = /C:.../ws/source.dir/target/test-classes/package/

所以,要到达src/rest/resources,我们需要在文件树中上下移动。这两种方法都可以使用。请注意,我们不能使用getResource(resourceFolderName),因为该文件夹不在目标文件夹中。希望没有人将资源放在创建的文件夹中。
如果类在插件中的包中,则相同测试的输出将是:
loaderDir = /C:.../ws/plugin/bin/
 localDir = /C:.../ws/plugin/bin/package/

因此,我们需要再次上下浏览文件夹树。


最有趣的情况是当包在插件中启动时。例如,作为JUnit插件测试。输出为:

loaderDir = /C:.../ws/plugin/
 localDir = /package/

我们只有将两个函数的结果结合起来才能得到绝对路径。但这还不够。在它们之间,我们应该放置类包所在地相对于插件文件夹的本地路径。可能你需要在这里插入srcsrc/test/resource之类的东西。

您可以将代码插入到您的代码中并查看您拥有的路径。


2
返回文件或文件路径
URL resource = YourClass.class.getResource("abc");
File file = Paths.get(resource.toURI()).toFile(); // return a file
String filepath = Paths.get(resource.toURI()).toFile().getAbsolutePath();  // return file path

0
这对我来说很有效:
try {           
    java.net.URL YourClassDir = YourClass.class.getResource("YourClass.class");                 
    String YourClassActionDirStr = YourClassDir.toString();
    System.out.println(YourClassActionDirStr);        
} catch (Exception e) {
    System.out.println(e);
}   

结果:
文件:/C:/...目录

你能提供更多细节吗?并且解释一下它是如何运作的吗? - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接