在 Java 中使用相对路径打开资源
Posted
技术标签:
【中文标题】在 Java 中使用相对路径打开资源【英文标题】:open resource with relative path in Java 【发布时间】:2021-11-11 21:42:16 【问题描述】:在我的 Java 应用程序中,我需要获取一些文件和目录。
这是程序结构:
./main.java
./package1/guiclass.java
./package1/resources/resourcesloader.java
./package1/resources/repository/modules/ -> this is the dir I need to get
./package1/resources/repository/SSL-Key/cert.jks -> this is the file I need to get
guiclass
加载资源加载器类,该类将加载我的资源(目录和文件)。
关于文件,我试过了
resourcesloader.class.getClass().getResource("repository/SSL-Key/cert.jks").toString()
为了得到真正的路径,但是这种方式行不通。
我不知道该目录使用哪个路径。
【问题讨论】:
class.getClass() 与 class.getClassLoader() 不同。还有另一种解决方案, getResourceAsStream() 使用与您的资源相同的包中的类。更多详情:tshikatshikaaa.blogspot.nl/2012/07/…. 另见***.com/questions/204784/… 【参考方案1】:我在使用getClass().getResource("filename.txt")
方法时遇到了问题。
在阅读 Java 文档说明后,如果您的资源与您尝试从中访问资源的类不在同一个包中,那么您必须为其提供以 '/'
开头的相对路径。推荐的策略是将您的资源文件放在根目录中的“资源”文件夹下。因此,例如,如果您有以下结构:
src/main/com/mycompany/myapp
然后你可以按照maven的推荐添加一个资源文件夹:
src/main/resources
此外,您可以在资源文件夹中添加子文件夹
src/main/resources/textfiles
并说你的文件名为myfile.txt
,所以你有
src/main/resources/textfiles/myfile.txt
现在出现了愚蠢的路径问题。假设您的com.mycompany.myapp package
中有一个类,并且您想从资源文件夹访问myfile.txt
文件。有人说您需要提供:
"/main/resources/textfiles/myfile.txt" path
或
"/resources/textfiles/myfile.txt"
这两个都是错误的。在我运行mvn clean compile
之后,文件和文件夹被复制到:
myapp/target/classes
文件夹。但是资源文件夹不存在,只有资源文件夹中的文件夹。所以你有:
myapp/target/classes/textfiles/myfile.txt
myapp/target/classes/com/mycompany/myapp/*
所以给getClass().getResource("")
方法的正确路径是:
"/textfiles/myfile.txt"
这里是:
getClass().getResource("/textfiles/myfile.txt")
这将不再返回 null,而是返回你的类。
我希望这对某人有所帮助。我很奇怪,"resources"
文件夹也没有被复制,而只是"resources"
文件夹中的子文件夹和文件。在我看来,"resources"
文件夹也可以在"myapp/target/classes"
下找到
【讨论】:
在我的target/classes
,我只能看到主要资源下的文件,不能看到测试资源。为什么?
@Ava 添加测试文件夹作为源文件夹,一切顺利!
@Ava,确定这对你来说是迟到的答案,但可能会对某人有所帮助。您需要执行mvn clean test-compile
命令,因为它在Maven lifecycle 中执行compile
。这将生成target/test-classes
。【参考方案2】:
提供相对于类加载器的路径,而不是您从中获取加载器的类。例如:
resourcesloader.class.getClassLoader().getResource("package1/resources/repository/SSL-Key/cert.jks").toString();
【讨论】:
【参考方案3】:希望为那些没有像其他人那样快速掌握此内容的人提供更多信息,我想提供我的场景,因为它的设置略有不同。我的项目设置了以下目录结构(使用 Eclipse):
项目/ src/ // 应用程序源代码 组织/ 我的项目/ MyClass.java test/ // 单元测试 res/ // 资源 images/ // 图标的 PNG 图像 我的图像.png xml/ // XSD 文件,用于使用 JAXB 验证 XML 文件 我的架构.xsd conf/ // Log4j 的默认 .conf 文件 log4j.conf lib/ // 通过项目设置添加到构建路径的库我在从 res 目录加载资源时遇到问题。我希望我的所有资源都与我的源代码分开(仅出于管理/组织目的)。所以,我要做的就是将 res 目录添加到 build-path 中,然后通过以下方式访问资源:
static final ClassLoader loader = MyClass.class.getClassLoader();
// in some function
loader.getResource("images/my-image.png");
loader.getResource("xml/my-schema.xsd");
loader.getResource("conf/log4j.conf");
注意:/
从资源字符串的开头被省略,因为我使用的是ClassLoader.getResource(String) 而不是Class.getResource(String)。
【讨论】:
.+1 建议使用 ClassLoader 这个主题的最佳答案!关于不在资源路径开头使用/
的提示是关键!【参考方案4】:
在 Class 上使用“getResource”时,将根据 Class 所在的包解析相对路径。在 ClassLoader 上使用“getResource”时,将根据根文件夹解析相对路径。
如果您使用绝对路径,则两个 'getResource' 方法都将从根文件夹开始。
【讨论】:
别忘了/
的效果
@nbeyer 为什么使用带有绝对路径的getResource
从根文件夹开始?绝对路径的目的不是absolute吗?【参考方案5】:
@GianCarlo: 您可以尝试调用系统属性 user.dir,它会为您提供 java 项目的根目录,然后将此路径附加到您的相对路径,例如:
String root = System.getProperty("user.dir");
String filepath = "/path/to/yourfile.txt"; // in case of Windows: "\\path \\to\\yourfile.txt
String abspath = root+filepath;
// using above path read your file into byte []
File file = new File(abspath);
FileInputStream fis = new FileInputStream(file);
byte []filebytes = new byte[(int)file.length()];
fis.read(filebytes);
【讨论】:
OP 想要在类路径中定位资源(很可能在构建期间生成的 jar 中)。此方法不提供实现该目标的方法 - 您不能将File
指向 jar 文件中的资源,只能指向文件系统中的正确条目(例如 jar 本身)。
我喜欢让“user.dir”查看所需路径的想法。谢谢【参考方案6】:
对于那些使用 eclipse + maven 的人。假设您尝试访问src/main/resources
中的文件images/pic.jpg
。这样做:
ClassLoader loader = MyClass.class.getClassLoader();
File file = new File(loader.getResource("images/pic.jpg").getFile());
完全正确,但可能导致空指针异常。似乎 eclipse 无法立即将 maven 目录结构中的文件夹识别为源文件夹。通过从项目的源文件夹列表中删除 src/main/resources
文件夹并将其放回(项目>属性>java构建路径>源>删除/添加文件夹),我能够解决这个问题。
【讨论】:
【参考方案7】:resourcesloader.class.getClass()
可以分解为:
Class<resourcesloader> clazz = resourceloader.class;
Class<Class> classClass = clazz.getClass();
这意味着您正在尝试使用引导类加载资源。
相反,您可能想要这样的东西:
resourcesloader.class.getResource("repository/SSL-Key/cert.jks").toString()
如果只有 javac 警告在非静态上下文中调用静态方法...
【讨论】:
【参考方案8】:以下是否有效?
resourcesloader.class.getClass().getResource("/package1/resources/repository/SSL-Key/cert.jks")
是否有不能指定包含包的完整路径的原因?
【讨论】:
【参考方案9】:选择上面提到的两个答案。第一个
resourcesloader.class.getClassLoader().getResource("package1/resources/repository/SSL-Key/cert.jks").toString();
resourcesloader.class.getResource("repository/SSL-Key/cert.jks").toString()
应该是一回事吗?
【讨论】:
【参考方案10】:为了获得文件的真实路径,你可以试试这个:
URL fileUrl = Resourceloader.class.getResource("resources/repository/SSL-Key/cert.jks");
String pathToClass = fileUrl.getPath;
Resourceloader 在这里是类名。 “resources/repository/SSL-Key/cert.jks”是文件的相对路径。如果您在 ./package1/java 中有您的 guiclass 并保留了其余文件夹结构,则由于定义了相对路径的规则,您会将“../resources/repository/SSL-Key/cert.jks”作为相对路径。
这样您就可以使用 BufferedReader 读取文件。不要使用字符串来标识文件的路径,因为如果你的路径中有空格或某些非英文字母的字符,你会遇到问题并且找不到文件。
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(fileUrl.openStream()));
【讨论】:
【参考方案11】:我对@jonathan.cone 的一个衬里进行了小修改(通过添加.getFile()
)以避免空指针异常,并设置数据目录的路径。这对我有用:
String realmID = new java.util.Scanner(new java.io.File(RandomDataGenerator.class.getClassLoader().getResource("data/aa-qa-id.csv").getFile().toString())).next();
【讨论】:
【参考方案12】:使用这个:
resourcesloader.class.getClassLoader().getResource("/path/to/file").**getPath();**
【讨论】:
【参考方案13】:在所有操作系统上工作的稳定方法之一是获取System.getProperty("user.dir")
String filePath = System.getProperty("user.dir") + "/path/to/file.extension";
Path path = Paths.get(filePath);
if (Files.exists(path))
return true;
【讨论】:
以上是关于在 Java 中使用相对路径打开资源的主要内容,如果未能解决你的问题,请参考以下文章