【问题标题】:open resource with relative path in Java在 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()

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

我不知道该目录使用哪个路径。

【问题讨论】:

标签: java resources loading


【解决方案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;
                  }
                  

                  【讨论】:

                    猜你喜欢
                    • 2013-01-06
                    • 1970-01-01
                    • 1970-01-01
                    • 2010-09-18
                    • 2010-12-08
                    • 2011-12-15
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多