在 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 中使用相对路径打开资源的主要内容,如果未能解决你的问题,请参考以下文章

在java中怎么获取页面的路径

Vue项目打包后的资源引用如何使用相对路径

java web项目 相对路径怎么写

java程序读取资源文件时路径如何指定

webpack+vuecli打包生成资源相对引用路径与背景图片的正确引用

spring 类路径资源中的相对路径