【问题标题】:Listing files with getResourceAsStream() is empty when run on command line在命令行上运行时,使用 getResourceAsStream() 列出文件为空
【发布时间】:2017-10-11 02:48:37
【问题描述】:

我正在尝试在我的应用程序的 jar 文件中列出特定路径中的文件。它在我使用“mvn clean package”构建时有效,但是当我在命令行上使用“java -jar target/myproject_1.0.jar”运行时,文件列表为空。基于this suggestion,我正在用这段代码读取目录内容

    boolean failed = true;
    String schemaLocation = "/xml";
    System.out.println("Scanning folder "+schemaLocation);
    InputStream dirStream = getClass().getResourceAsStream(schemaLocation);
    BufferedReader dirReader = new BufferedReader(new InputStreamReader( dirStream ));
    try{
        String filename = dirReader.readLine();
        while( filename != null ){
            failed = false;
            if( filename.endsWith(".xsd")){
                String fullname = schemaLocation+"/"+filename;
                System.out.println("Loading schema file "+fullname );
                InputStream in = getClass().getResourceAsStream(schemaLocation+"/"+filename);
                readAndProcessSchema(in);
            }
            filename = dirReader.readLine();
        }
    }catch(IOException ex){
        ex.printStackTrace();
    }
    if(failed){
        System.out.println("Fallback enabled.");
        InputStream in = getClass().getResourceAsStream(schemaLocation+"/schema_v1.0.xsd");
        readAndProcessSchema(in);
    }

注意流不是空的,只是空的。并且只有路径列表逻辑失败,因为代码示例末尾的后备代码(读取硬编码的 xsd 文件名)甚至在命令行上也有效。我也尝试过MyClass.class.getResourceAsStream("/xml")(基于this suggestion),结果相同。

另一个可能相关的注意事项是 xml 路径的内容来自我项目的一个依赖项,我无法预测它们将来可能添加哪些其他文件(因此我需要扫描该路径)。为了引入这些依赖项,我使用了来自 this post 的建议,我相信它是有效的,因为 jar 文件的目录似乎包含所有内容:

 $ jar -tvf target/myproject-1.0.jar | grep xml
      0 Tue Oct 10 10:02:28 PDT 2017 xml/
   1999 Tue Oct 10 10:02:28 PDT 2017 xml/schema_v1.0.xsd
   4474 Tue Oct 10 10:02:28 PDT 2017 xml/schema_v2.0.xsd
   5757 Fri Oct 06 16:07:48 PDT 2017 META-INF/maven/com.mycompany/myproject/pom.xml

值得一提的是,这是作为 Spring Boot 应用程序运行的,使用他们的 spring-boot-maven-plugin “重新打包”目标构建。我不仅想知道现在要解决这个问题,还想知道为什么类路径在 Maven 单元测试中的工作方式与在命令行中不同。

【问题讨论】:

  • 虽然我仍然不知道为什么这在单元测试中有效但在命令行中无效,@ptomli 用一种更紧凑的替代方法向我指出了a threadResource[] xsdFiles = resourceResolver.getResources("classpath:/xml/*.xsd"); 然后迭代 xsdFiles

标签: java embedded-resource


【解决方案1】:
org.apache.commons.io.IOUtils.toString(getClass().getResourceAsStream("/csv/test.csv"), Charset.forName("UTF-8")))

这是如何访问 jar 文件中的内部源代码的示例。

这很棘手,资源的根路径是什么。在 IDE 中,您可以将某个文件夹(例如 webapp/recource)标记为 resource 文件夹。并且当您构建 jar 文件时,资源文件夹内容将在根目录中。所以如果你从/开始你的资源路径,这意味着jar的根目录(即资源文件夹的根目录)

我不使用相对路径,因此您可以查看open resource with relative path in java 以获取更多信息。

【讨论】:

  • 感谢您的建议,但我正在尝试发现特定路径 (/xml) 上的可用资源。一旦我知道它们的名称,我就可以在该路径中加载资源,但我无法获得那里存在的资源列表。
【解决方案2】:

您的代码正在使用Class#getResourceAsStream,它将使用类的类加载器。这可能适用于您的 IDE 或 Maven,但可能不适用于其他情况。

实际上,您可能应该尝试使用线程上下文类加载器Thread.currentThread().getContextClassLoader(),如果失败则回退。

有一个类似的问题Get a list of resources from classpath directory

当然,按照那里的建议,您可以使用 Spring 工具,PathMatchingResourcePatternResolver

【讨论】:

  • 我尝试了Thread.currentThread().getContextClassLoader().getResourceAsStream("/xml"),这为我返回了一个空指针。我也尝试了 Spring resolver suggestion ,但 IIRC 抱怨“/xml”是无效路径。我会再试一次。
  • 我的记忆不正确。使用 Spring 的ResourceLoader.getResource().getInputStream() 给了我与getClass().getResourceAsStream 相同的结果。具体来说,它为资源路径提供了一个空流,但加载 xsd 文件就好了。
  • 一旦我停止像 Class.getResourceAsStream() 那样尝试使用 Spring ResourceLoader 方法,我就能够让它工作。谢谢!
猜你喜欢
  • 1970-01-01
  • 2023-04-09
  • 2019-01-20
  • 2019-08-11
  • 2018-03-12
  • 1970-01-01
  • 2016-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多