从classpath目录获取资源列表

我正在寻找一种方法来获取从给定的类path目录中的所有资源名称的列表,如方法List<String> getResourceNames (String directoryName)

例如,给定包含文件a.htmlb.htmlc.html和子目录d的类path目录x/y/zgetResourceNames("x/y/z")应返回包含以下内容的List<String>string: ['a.html', 'b.html', 'c.html', 'd']

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

我知道我可以用FileJarFileURL来写一个快速的代码片段,但是我不想重复发明。 我的问题是,考虑到现有的公共库,实现getResourceNames最快捷的方法是什么? Spring和Apache Commons栈都是可行的。

自定义扫描仪

实施您自己的扫描仪。 例如:

  private List<String> getResourceFiles( String path ) throws IOException { List<String> filenames = new ArrayList<>(); try( InputStream in = getResourceAsStream( path ); BufferedReader br = new BufferedReader( new InputStreamReader( in ) ) ) { String resource; while( (resource = br.readLine()) != null ) { filenames.add( resource ); } } return filenames; } private InputStream getResourceAsStream( String resource ) { final InputStream in = getContextClassLoader().getResourceAsStream( resource ); return in == null ? getClass().getResourceAsStream( resource ) : in; } private ClassLoader getContextClassLoader() { return Thread.currentThread().getContextClassLoader(); } 

Spring框架

使用Spring Framework的PathMatchingResourcePatternResolver

Ronmamoreflection

对于巨大的CLASSPATH值,其他技术在运行时可能会很慢。 更快的解决scheme是使用ronmamo的Reflections API ,它在编译时预编译search。

这是代码
资料来源 :forums.devx.com/showthread.php?t=153784

 import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; /** * list resources available from the classpath @ * */ public class ResourceList{ /** * for all elements of java.class.path get a Collection of resources Pattern * pattern = Pattern.compile(".*"); gets all resources * * @param pattern * the pattern to match * @return the resources in the order they are found */ public static Collection<String> getResources( final Pattern pattern){ final ArrayList<String> retval = new ArrayList<String>(); final String classPath = System.getProperty("java.class.path", "."); final String[] classPathElements = classPath.split(System.getProperty("path.separator")); for(final String element : classPathElements){ retval.addAll(getResources(element, pattern)); } return retval; } private static Collection<String> getResources( final String element, final Pattern pattern){ final ArrayList<String> retval = new ArrayList<String>(); final File file = new File(element); if(file.isDirectory()){ retval.addAll(getResourcesFromDirectory(file, pattern)); } else{ retval.addAll(getResourcesFromJarFile(file, pattern)); } return retval; } private static Collection<String> getResourcesFromJarFile( final File file, final Pattern pattern){ final ArrayList<String> retval = new ArrayList<String>(); ZipFile zf; try{ zf = new ZipFile(file); } catch(final ZipException e){ throw new Error(e); } catch(final IOException e){ throw new Error(e); } final Enumeration e = zf.entries(); while(e.hasMoreElements()){ final ZipEntry ze = (ZipEntry) e.nextElement(); final String fileName = ze.getName(); final boolean accept = pattern.matcher(fileName).matches(); if(accept){ retval.add(fileName); } } try{ zf.close(); } catch(final IOException e1){ throw new Error(e1); } return retval; } private static Collection<String> getResourcesFromDirectory( final File directory, final Pattern pattern){ final ArrayList<String> retval = new ArrayList<String>(); final File[] fileList = directory.listFiles(); for(final File file : fileList){ if(file.isDirectory()){ retval.addAll(getResourcesFromDirectory(file, pattern)); } else{ try{ final String fileName = file.getCanonicalPath(); final boolean accept = pattern.matcher(fileName).matches(); if(accept){ retval.add(fileName); } } catch(final IOException e){ throw new Error(e); } } } return retval; } /** * list the resources that match args[0] * * @param args * args[0] is the pattern to match, or list all resources if * there are no args */ public static void main(final String[] args){ Pattern pattern; if(args.length < 1){ pattern = Pattern.compile(".*"); } else{ pattern = Pattern.compile(args[0]); } final Collection<String> list = ResourceList.getResources(pattern); for(final String name : list){ System.out.println(name); } } } 

如果您使用的是Spring,请查看PathMatchingResourcePatternResolver

如果您使用apache commonsIO,您可以使用文件系统(可选带扩展筛选器):

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

和资源/ classpath:

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

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

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

要么

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

在通话之前和两者结合使用…

使用Google Reflections:

 Reflections reflections = new Reflections(null, new ResourcesScanner()); Set<String> resourceList = reflections.getResources(x -> true); 

另一个示例:从some.package获取扩展名为.csv的所有文件:

 Reflections reflections = new Reflections("some.package", new ResourcesScanner()); Set<String> fileNames = reflections.getResources(Pattern.compile(".*\\.csv")); 

所以就PathMatchingResourcePatternResolver而言,这是代码中所需要的:

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

使用Rob的响应组合。

 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 } 

根据上面的@rob的信息,我创build了我向公有领域发布的实现:

 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在目录上工作,但确实如此,它运作良好。