代码之家  ›  专栏  ›  技术社区  ›  Marat Salikhov

从类路径目录中获取资源列表

  •  205
  • Marat Salikhov  · 技术社区  · 15 年前

    我正在寻找一种从给定的类路径目录中获取所有资源名列表的方法,类似于方法 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中的资源。

    我知道我可以用 File s, JarFile s和 URL getResourceNames ? Spring和Apache Commons堆栈都是可行的。

    11 回复  |  直到 15 年前
        1
  •  159
  •   StaticBR    7 年前

    自定义扫描仪

    安装自己的扫描仪。例如:

    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();
    }
    

    使用 PathMatchingResourcePatternResolver 来自Spring框架。

    朗马莫反射

    对于巨大的类路径值,其他技术在运行时可能会比较慢。一个更快的解决方案是使用ronmamo的 Reflections API ,它在编译时预编译搜索。

        2
  •  51
  •   FoxAlfaBravo Jigar Joshi    10 年前

    这是密码
    来源 :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);
            }
        }
    }  
    

    如果你用的是弹簧,看看 PathMatchingResourcePatternResolver

        3
  •  24
  •   dutoitns    6 年前

    使用 Reflections

    在类路径上获取所有内容:

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

    另一个例子-获取扩展名为 .csv文件 一些包裹

    Reflections reflections = new Reflections("some.package", new ResourcesScanner());
    Set<String> fileNames = reflections.getResources(Pattern.compile(".*\\.csv"));
    
        4
  •  16
  •   Jared Burrows    7 年前

    如果使用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);
    

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

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

    在打电话之前,两者结合使用。。。

        5
  •  12
  •   Jared Burrows    7 年前

    因此,对于PathMatchIngressourcePatternResolver,这是代码中需要的:

    @Autowired
    ResourcePatternResolver resourceResolver;
    
    public void getResources() {
      resourceResolver.getResources("classpath:config/*.xml");
    }
    
        6
  •  5
  •   BullyWiiPlaza    8 年前

    这个 Spring framework PathMatchingResourcePatternResolver 对这些事情来说真是太棒了:

    private Resource[] getXMLResources() throws IOException
    {
        ClassLoader classLoader = MethodHandles.lookup().getClass().getClassLoader();
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(classLoader);
    
        return resolver.getResources("classpath:x/y/z/*.xml");
    }
    

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>LATEST</version>
    </dependency>
    
        7
  •  5
  •   Charlie    6 年前

    结合罗布的反应。

    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
    }
    
        8
  •  3
  •   naXa stands with Ukraine    7 年前

    有了春天就容易了。无论是一个文件、文件夹,甚至是多个文件,都有可能通过注入来实现。

    x/y/z 文件夹。

    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.core.io.Resource;
    import org.springframework.stereotype.Service;
    
    @Service
    public class StackoverflowService {
        @Value("classpath:x/y/z/*")
        private Resource[] resources;
    
        public List<String> getResourceNames() {
            return Arrays.stream(resources)
                    .map(Resource::getFilename)
                    .collect(Collectors.toList());
        }
    }
    

    它对文件系统和jar中的资源都有效。

        9
  •  3
  •   Enrico Giurin    7 年前

    这应该有效(如果弹簧不是一个选项):

    public static List<String> getFilenamesForDirnameFromCP(String directoryName) throws URISyntaxException, UnsupportedEncodingException, IOException {
        List<String> filenames = new ArrayList<>();
    
        URL url = Thread.currentThread().getContextClassLoader().getResource(directoryName);
        if (url != null) {
            if (url.getProtocol().equals("file")) {
                File file = Paths.get(url.toURI()).toFile();
                if (file != null) {
                    File[] files = file.listFiles();
                    if (files != null) {
                        for (File filename : files) {
                            filenames.add(filename.toString());
                        }
                    }
                }
            } else if (url.getProtocol().equals("jar")) {
                String dirname = directoryName + "/";
                String path = url.getPath();
                String jarPath = path.substring(5, path.indexOf("!"));
                try (JarFile jar = new JarFile(URLDecoder.decode(jarPath, StandardCharsets.UTF_8.name()))) {
                    Enumeration<JarEntry> entries = jar.entries();
                    while (entries.hasMoreElements()) {
                        JarEntry entry = entries.nextElement();
                        String name = entry.getName();
                        if (name.startsWith(dirname) && !dirname.equals(name)) {
                            URL resource = Thread.currentThread().getContextClassLoader().getResource(name);
                            filenames.add(resource.toString());
                        }
                    }
                }
            }
        }
        return filenames;
    }
    
        10
  •  1
  •   Luke Hutchison    6 年前

    列出类路径中所有资源的最可靠机制是 to use this pattern with ClassGraph ,因为它处理 widest possible array of classpath specification mechanisms ,包括新的JPMS模块系统。(我是ClassGraph的作者。)

    List<String> resourceNames;
    try (ScanResult scanResult = new ClassGraph().whitelistPaths("x/y/z").scan()) {
        resourceNames = scanResult.getAllResources().getNames();
    }
    
        11
  •  1
  •   Jacques Koorts    6 年前

    我的方式,没有弹簧,在单元测试中使用:

    URI uri = TestClass.class.getResource("/resources").toURI();
    Path myPath = Paths.get(uri);
    Stream<Path> walk = Files.walk(myPath, 1);
    for (Iterator<Path> it = walk.iterator(); it.hasNext(); ) {
        Path filename = it.next();   
        System.out.println(filename);
    }
    
        12
  •  0
  •   mkobit    7 年前

    我想你可以利用[ Zip文件系统提供程序 ][1] 为了达到这个目的。使用时 FileSystems.newFileSystem 看起来您可以将该ZIP中的对象视为“常规”文件。

    在上面的链接文档中:

    在传递给 文件系统.newFileSystem 方法。有关Zip文件系统的特定于提供程序的配置属性的信息,请参阅[Zip文件系统属性][2]主题。

    一旦有了zip文件系统的实例,就可以调用[ java.nio.file.FileSystem java.nio.file.Path ][4] 类来执行复制、移动和重命名文件以及修改文件属性等操作。

    jdk.zipfs [Java 11状态][5]中的模块:

    zip文件系统提供程序将zip或JAR文件视为文件系统,并提供操作文件内容的能力。zip文件系统提供程序可以由[ 文件系统.newFileSystem

    下面是一个我使用示例资源设计的示例。注意a .zip 是一个 .jar ,但您可以调整代码以使用类路径资源:

    安装程序

    cd /tmp
    mkdir -p x/y/z
    touch x/y/z/{a,b,c}.html
    echo 'hello world' > x/y/z/d
    zip -r example.zip x
    

    爪哇

    import java.io.IOException;
    import java.net.URI;
    import java.nio.file.FileSystem;
    import java.nio.file.FileSystems;
    import java.nio.file.Files;
    import java.util.Collections;
    import java.util.stream.Collectors;
    
    public class MkobitZipRead {
    
      public static void main(String[] args) throws IOException {
        final URI uri = URI.create("jar:file:/tmp/example.zip");
        try (
            final FileSystem zipfs = FileSystems.newFileSystem(uri, Collections.emptyMap());
        ) {
          Files.walk(zipfs.getPath("/")).forEach(path -> System.out.println("Files in zip:" + path));
          System.out.println("-----");
          final String manifest = Files.readAllLines(
              zipfs.getPath("x", "y", "z").resolve("d")
          ).stream().collect(Collectors.joining(System.lineSeparator()));
          System.out.println(manifest);
        }
      }
    
    }
    

    输出

    Files in zip:/
    Files in zip:/x/
    Files in zip:/x/y/
    Files in zip:/x/y/z/
    Files in zip:/x/y/z/c.html
    Files in zip:/x/y/z/b.html
    Files in zip:/x/y/z/a.html
    Files in zip:/x/y/z/d
    -----
    hello world
    
        13
  •  0
  •   kukis    7 年前

    @Value("file:*/**/resources/**/schema/*.json")
    private Resource[] resources;
    
        14
  •  -5
  •   Deven Phillips    10 年前

    基于@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 在一个目录中这样工作,它确实可以,而且工作得很好。

    推荐文章