从classpath目录获取资源列表
我正在寻找一种方法来获取从给定的类path目录中的所有资源名称的列表,如方法List<String> getResourceNames (String directoryName)
。
例如,给定包含文件a.html
, b.html
, c.html
和子目录d
的类path目录x/y/z
, getResourceNames("x/y/z")
应返回包含以下内容的List<String>
string: ['a.html', 'b.html', 'c.html', 'd']
。
它应该同时用于文件系统和jar子中的资源。
我知道我可以用File
, JarFile
和URL
来写一个快速的代码片段,但是我不想重复发明。 我的问题是,考虑到现有的公共库,实现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
在目录上工作,但确实如此,它运作良好。