在Java中使用相对路径打开资源


84

在我的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类,该类将加载我的资源(目录和文件)。

至于文件,我试过了

resourcesloader.class.getClass().getResource("repository/SSL-Key/cert.jks").toString()

为了获得真实的路径,但是这种方式行不通。

我不知道如何执行目录。


1
class.getClass()与class.getClassLoader()不同。还有另一种解决方案,getResourceAsStream()使用与资源相同的包中的类。有关更多详细信息:tshikatshikaaa.blogspot.nl/2012/07/…
杰罗姆Verstrynge

Answers:


48

提供相对于类加载器的路径,而不是要从中获取加载器的类。例如:

resourcesloader.class.getClassLoader().getResource("package1/resources/repository/SSL-Key/cert.jks").toString();

160

我在使用该getClass().getResource("filename.txt")方法时遇到问题。阅读Java文档说明后,如果您的资源与尝试从中访问资源的类不在同一个包中,则必须给它相对路径,以开头'/'。推荐的策略是将资源文件放在根目录下的“ resources”文件夹下。因此,例如,如果您具有以下结构:

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"


1
在我的中target/classes,我只能看到主要资源下的文件,而不能测试资源。为什么?
2015年

@Ava将测试文件夹添加为您的源文件夹,您一切顺利!
Aakash Parashar

@Ava,请确定这是您的最新答案,但可能会对某人有所帮助。您需要执行mvn clean test-compile命令,因为它去后compileMaven的生命周期。那会产生target/test-classes
亚历山大·拉琴科

34

希望为那些没有像其他人一样迅速了解这些信息的人提供更多信息,我想提供我的方案,因为它的设置略有不同。我的项目使用以下目录结构进行了设置(使用Eclipse):

项目/
  src / //应用程序源代码
    组织/
      我的项目/
        MyClass.java
  测试///单元测试
  res / //资源
    images / //图标的PNG图片
      my-image.png
    xml / //用于使用JAXB验证XML文件的XSD文件
      我的模式
    conf / // Log4j的默认.conf文件
      log4j.conf
  lib / //通过项目设置将库添加到构建路径

我在从res目录加载资源时遇到问题。我希望所有资源都与源代码分开(仅出于管理/组织目的)。因此,我要做的是将res目录添加到构建路径,然后通过以下方式访问资源:

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方法,(串),而不是Class.getResource(字符串)


1
。+ 1建议使用ClassLoader
pyb 2014年

1
关于这个问题的最佳答案!关于不使用的提示/资源路径开头是关键!
Kayhadrin

10

在类上使用'getResource'时,将基于该类所在的包来解析相对路径。在类加载器上使用'getResource'时,将根据根文件夹来解析相对路径。

如果使用绝对路径,则两个“ getResource”方法都将从根文件夹开始。


不要忘记/
Gilberto

@nbeyer为什么使用getResource绝对路径从根文件夹开始?绝对路径的目的不是绝对的吗?
atjua

10

@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);

1
OP希望在类路径中找到资源(最有可能在构建期间生成的jar中)。此方法无法提供实现该目标的方法-您不能File将a指向jar文件中的资源,而只能指向文件系统中的正确条目(例如jar本身)。
Attila 2013年

我喜欢让“ user.dir”查看所需路径的想法。谢谢
YouAreAwesome

5

对于那些使用Eclipse + Maven的人。假设您尝试访问该文件images/pic.jpgsrc/main/resources。这样做:

ClassLoader loader = MyClass.class.getClassLoader();
File file = new File(loader.getResource("images/pic.jpg").getFile());

是完全正确的,但可能导致空指针异常。似乎eclipse不能立即将maven目录结构中的文件夹识别为源文件夹。通过src/main/resources从项目的源文件夹列表中删除该文件夹并将其放回去(项目>属性> Java构建路径>源>删除/添加文件夹),我能够解决此问题。


2
resourcesloader.class.getClass()

可以分解为:

Class<resourcesloader> clazz = resourceloader.class;
Class<Class> classClass = clazz.getClass();

这意味着您正在尝试使用引导类加载资源。

相反,您可能想要以下内容:

resourcesloader.class.getResource("repository/SSL-Key/cert.jks").toString()

如果只有Javac警告有关在非静态上下文中调用静态方法...


1

从事以下工作吗?

resourcesloader.class.getClass().getResource("/package1/resources/repository/SSL-Key/cert.jks")

您是否有理由无法指定包含软件包的完整路径?


1

如上所述,给出两个答案。第一个

resourcesloader.class.getClassLoader().getResource("package1/resources/repository/SSL-Key/cert.jks").toString();
resourcesloader.class.getResource("repository/SSL-Key/cert.jks").toString()

应该是一回事吗?


1

为了获得文件的真实路径,您可以尝试以下操作:

URL fileUrl = Resourceloader.class.getResource("resources/repository/SSL-Key/cert.jks");
String pathToClass = fileUrl.getPath;    

Resourceloader在这里是类名。“ resources / repository / SSL-Key / cert.jks”是文件的相对路径。如果您的guiclass位于./package1/java中,而其余的文件夹结构仍然保留,则由于定义了相对路径的规则,您将采用“ ../resources/repository/SSL-Key/cert.jks”作为相对路径。

这样,您可以使用BufferedReader读取文件。请勿使用STRING来标识文件的路径,因为如果路径中包含空格或某些非英语字母的字符,则会出现问题,并且找不到文件。

BufferedReader bufferedReader = new BufferedReader(
                        new InputStreamReader(fileUrl.openStream()));

0

我对@ 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();

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.