Get a list of resources from classpath directory

前端 未结 14 879
予麋鹿
予麋鹿 2020-11-22 05:20

I am looking for a way to get a list of all resource names from a given classpath directory, something like a method List getResourceNames (String direct

相关标签:
14条回答
  • 2020-11-22 05:52

    Using Reflections

    Get everything on the classpath:

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

    Another example - get all files with extension .csv from some.package:

    Reflections reflections = new Reflections("some.package", new ResourcesScanner());
    Set<String> fileNames = reflections.getResources(Pattern.compile(".*\\.csv"));
    
    0 讨论(0)
  • 2020-11-22 05:56

    Here is the code
    Source: 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);
            }
        }
    }  
    

    If you are using Spring Have a look at PathMatchingResourcePatternResolver

    0 讨论(0)
  • 2020-11-22 05:56

    So in terms of the PathMatchingResourcePatternResolver this is what is needed in the code:

    @Autowired
    ResourcePatternResolver resourceResolver;
    
    public void getResources() {
      resourceResolver.getResources("classpath:config/*.xml");
    }
    
    0 讨论(0)
  • 2020-11-22 05:56

    The Spring framework's PathMatchingResourcePatternResolver is really awesome for these things:

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

    Maven dependency:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>LATEST</version>
    </dependency>
    
    0 讨论(0)
  • 2020-11-22 05:57

    I think you can leverage the [Zip File System Provider][1] to achieve this. When using FileSystems.newFileSystem it looks like you can treat the objects in that ZIP as a "regular" file.

    In the linked documentation above:

    Specify the configuration options for the zip file system in the java.util.Map object passed to the FileSystems.newFileSystem method. See the [Zip File System Properties][2] topic for information about the provider-specific configuration properties for the zip file system.

    Once you have an instance of a zip file system, you can invoke the methods of the [java.nio.file.FileSystem][3] and [java.nio.file.Path][4] classes to perform operations such as copying, moving, and renaming files, as well as modifying file attributes.

    The documentation for the jdk.zipfs module in [Java 11 states][5]:

    The zip file system provider treats a zip or JAR file as a file system and provides the ability to manipulate the contents of the file. The zip file system provider can be created by [FileSystems.newFileSystem][6] if installed.

    Here is a contrived example I did using your example resources. Note that a .zip is a .jar, but you could adapt your code to instead use classpath resources:

    Setup

    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
    

    Java

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

    Output

    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
    
    0 讨论(0)
  • 2020-11-22 06:00

    If you use apache commonsIO you can use for the filesystem (optionally with extension filter):

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

    and for resources/classpath:

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

    If you don't know if "directoy/" is in the filesystem or in resources you may add a

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

    or

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

    before the calls and use both in combination...

    0 讨论(0)
提交回复
热议问题