How to list the files inside a JAR file?

前端 未结 16 2241
温柔的废话
温柔的废话 2020-11-22 00:40

I have this code which reads all the files from a directory.

    File textFolder = new File(\"text_directory\");

    File [] texFiles = textFolder.listFiles         


        
相关标签:
16条回答
  • 2020-11-22 01:16

    So I guess my main problem would be, how to know the name of the jar where my main class lives.

    Assuming that your project is packed in a Jar (not necessarily true!), you can use ClassLoader.getResource() or findResource() with the class name (followed by .class) to get the jar that contains a given class. You'll have to parse the jar name from the URL that gets returned (not that tough), which I will leave as an exercise for the reader :-)

    Be sure to test for the case where the class is not part of a jar.

    0 讨论(0)
  • 2020-11-22 01:17

    The most robust mechanism for listing all resources in the classpath is currently to use this pattern with ClassGraph, because it handles the widest possible array of classpath specification mechanisms, including the new JPMS module system. (I am the author of ClassGraph.)

    How to know the name of the JAR file where my main class lives?

    URI mainClasspathElementURI;
    try (ScanResult scanResult = new ClassGraph().whitelistPackages("x.y.z")
            .enableClassInfo().scan()) {
        mainClasspathElementURI =
                scanResult.getClassInfo("x.y.z.MainClass").getClasspathElementURI();
    }
    

    How can I read the contents of a directory in a similar fashion within a JAR file?

    List<String> classpathElementResourcePaths;
    try (ScanResult scanResult = new ClassGraph().overrideClasspath(mainClasspathElementURI)
            .scan()) {
        classpathElementResourcePaths = scanResult.getAllResources().getPaths();
    }
    

    There are lots of other ways to deal with resources too.

    0 讨论(0)
  • 2020-11-22 01:18
    public static ArrayList<String> listItems(String path) throws Exception{
        InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(path);
        byte[] b = new byte[in.available()];
        in.read(b);
        String data = new String(b);
        String[] s = data.split("\n");
        List<String> a = Arrays.asList(s);
        ArrayList<String> m = new ArrayList<>(a);
        return m;
    }
    
    0 讨论(0)
  • 2020-11-22 01:19

    One more for the road:

    import java.io.IOException;
    import java.net.URISyntaxException;
    import java.nio.file.*;
    import java.util.ArrayList;
    import java.util.List;
    
    import static java.nio.file.FileSystems.newFileSystem;
    import static java.util.Collections.emptyMap;
    
    public class ResourceWalker {
      private static final PathMatcher FILE_MATCHER =
          FileSystems.getDefault().getPathMatcher( "glob:**.ttf" );
    
      public static List<Path> walk( final String directory )
          throws URISyntaxException, IOException {
        final List<Path> filenames = new ArrayList<>();
        final var resource = ResourceWalker.class.getResource( directory );
    
        if( resource != null ) {
          final var uri = resource.toURI();
          final var path = uri.getScheme().equals( "jar" )
              ? newFileSystem( uri, emptyMap() ).getPath( directory )
              : Paths.get( uri );
          final var walk = Files.walk( path, 10 );
    
          for( final var it = walk.iterator(); it.hasNext(); ) {
            final Path p = it.next();
            if( FILE_MATCHER.matches( p ) ) {
              filenames.add( p );
            }
          }
        }
    
        return filenames;
      }
    }
    

    This is a bit more flexible for matching specific filenames because it uses wildcard globbing.


    A more functional style:

    import java.io.IOException;
    import java.net.URISyntaxException;
    import java.nio.file.*;
    import java.util.function.Consumer;
    
    import static java.nio.file.FileSystems.newFileSystem;
    import static java.util.Collections.emptyMap;
    
    /**
     * Responsible for finding file resources.
     */
    public class ResourceWalker {
      private static final PathMatcher FILE_MATCHER =
          FileSystems.getDefault().getPathMatcher( "glob:**.ttf" );
    
      public static void walk( final String dirName, final Consumer<Path> f )
          throws URISyntaxException, IOException {
        final var resource = ResourceWalker.class.getResource( dirName );
    
        if( resource != null ) {
          final var uri = resource.toURI();
          final var path = uri.getScheme().equals( "jar" )
              ? newFileSystem( uri, emptyMap() ).getPath( dirName )
              : Paths.get( uri );
          final var walk = Files.walk( path, 10 );
    
          for( final var it = walk.iterator(); it.hasNext(); ) {
            final Path p = it.next();
            if( FILE_MATCHER.matches( p ) ) {
              f.accept( p );
            }
          }
        }
      }
    }
    
    0 讨论(0)
  • 2020-11-22 01:23

    erickson's answer worked perfectly:

    Here's the working code.

    CodeSource src = MyClass.class.getProtectionDomain().getCodeSource();
    List<String> list = new ArrayList<String>();
    
    if( src != null ) {
        URL jar = src.getLocation();
        ZipInputStream zip = new ZipInputStream( jar.openStream());
        ZipEntry ze = null;
    
        while( ( ze = zip.getNextEntry() ) != null ) {
            String entryName = ze.getName();
            if( entryName.startsWith("images") &&  entryName.endsWith(".png") ) {
                list.add( entryName  );
            }
        }
    
     }
     webimages = list.toArray( new String[ list.size() ] );
    

    And I have just modify my load method from this:

    File[] webimages = ... 
    BufferedImage image = ImageIO.read(this.getClass().getResource(webimages[nextIndex].getName() ));
    

    To this:

    String  [] webimages = ...
    
    BufferedImage image = ImageIO.read(this.getClass().getResource(webimages[nextIndex]));
    
    0 讨论(0)
  • 2020-11-22 01:31

    Just a different way of listing/reading files from a jar URL and it does it recursively for nested jars

    https://gist.github.com/trung/2cd90faab7f75b3bcbaa

    URL urlResource = Thead.currentThread().getContextClassLoader().getResource("foo");
    JarReader.read(urlResource, new InputStreamCallback() {
        @Override
        public void onFile(String name, InputStream is) throws IOException {
            // got file name and content stream 
        }
    });
    
    0 讨论(0)
提交回复
热议问题