我正在寻找一种方法来从给定的类路径目录中获得所有资源名称的列表,类似于方法list <String> getResourceNames (String directoryName)。

例如,给定一个类路径目录x/y/z,其中包含文件a.html, b.html, c.html和子目录d, getResourceNames("x/y/z")应该返回一个包含以下字符串的List<String>:['a.html', 'b.html', 'c.html', 'd']。

它应该同时适用于文件系统和jar中的资源。

我知道我可以用Files, JarFiles和url编写一个快速的片段,但我不想重新发明轮子。我的问题是,给定现有的公共可用库,实现getResourceNames的最快方法是什么?Spring和Apache Commons栈都是可行的。


当前回答

基于上面@rob的信息,我创建了一个实现,我将其发布到公共领域:

private static List<String> getClasspathEntriesByPath(String path) throws IOException {
    InputStream is = Main.class.getClassLoader().getResourceAsStream(path);

    StringBuilder sb = new StringBuilder();
    while (is.available()>0) {
        byte[] buffer = new byte[1024];
        sb.append(new String(buffer, Charset.defaultCharset()));
    }

    return Arrays
            .asList(sb.toString().split("\n"))          // Convert StringBuilder to individual lines
            .stream()                                   // Stream the list
            .filter(line -> line.trim().length()>0)     // Filter out empty lines
            .collect(Collectors.toList());              // Collect remaining lines into a List again
}

虽然我不期望getResourcesAsStream在目录上像那样工作,但它确实做到了,而且工作得很好。

其他回答

目前在类路径中列出所有资源的最健壮的机制是与ClassGraph一起使用这种模式,因为它处理了尽可能广泛的类路径规范机制,包括新的JPMS模块系统。(我是ClassGraph的作者。)

List<String> resourceNames;
try (ScanResult scanResult = new ClassGraph().acceptPaths("x/y/z").scan()) {
    resourceNames = scanResult.getAllResources().getNames();
}

所以在PathMatchingResourcePatternResolver方面,这是代码中需要的:

@Autowired
ResourcePatternResolver resourceResolver;

public void getResources() {
  resourceResolver.getResources("classpath:config/*.xml");
}

如果你使用apache commonsIO,你可以使用文件系统(可选扩展过滤器):

Collection<File> files = FileUtils.listFiles(new File("directory/"), null, false);

对于资源/类路径:

List<String> files = IOUtils.readLines(MyClass.class.getClassLoader().getResourceAsStream("directory/"), Charsets.UTF_8);

如果您不知道“directoy/”是在文件系统中还是在资源中,您可以添加一个

if (new File("directory/").isDirectory())

or

if (MyClass.class.getClassLoader().getResource("directory/") != null)

在调用和组合使用两者之前…

这两个答案都不适合我,即使我把我的资源放在资源文件夹里,并遵循上面的答案。真正让人觉得好笑的是:

@Value("file:*/**/resources/**/schema/*.json")
private Resource[] resources;

结合了罗伯的回答。

final String resourceDir = "resourceDirectory/";
List<String> files = IOUtils.readLines(Thread.currentThread().getClass().getClassLoader().getResourceAsStream(resourceDir), Charsets.UTF_8);

for (String f : files) {
  String data = IOUtils.toString(Thread.currentThread().getClass().getClassLoader().getResourceAsStream(resourceDir + f));
  // ... process data
}