¿Cómo enumerar los archivos dentro de un archivo JAR?

Resuelto OscarRyz asked hace 15 años • 17 respuestas

Tengo este código que lee todos los archivos de un directorio.

    File textFolder = new File("text_directory");

    File [] texFiles = textFolder.listFiles( new FileFilter() {
           public boolean accept( File file ) {
               return file.getName().endsWith(".txt");
           }
    });

Funciona muy bien. Llena la matriz con todos los archivos que terminan en ".txt" del directorio "text_directory".

¿Cómo puedo leer el contenido de un directorio de forma similar dentro de un archivo JAR?

Entonces, lo que realmente quiero hacer es enumerar todas las imágenes dentro de mi archivo JAR, para poder cargarlas con:

ImageIO.read(this.getClass().getResource("CompanyLogo.png"));

(Ese funciona porque el "CompanyLogo" está "codificado", pero la cantidad de imágenes dentro del archivo JAR puede ser de 10 a 200 de longitud variable).

EDITAR

Entonces supongo que mi principal problema sería: ¿Cómo saber el nombre del archivo JAR donde vive mi clase principal?

De acuerdo, pude leerlo usando java.util.Zip.

Mi estructura es así:

Ellos son como:

my.jar!/Main.class
my.jar!/Aux.class
my.jar!/Other.class
my.jar!/images/image01.png
my.jar!/images/image02a.png
my.jar!/images/imwge034.png
my.jar!/images/imagAe01q.png
my.jar!/META-INF/manifest 

Ahora puedo cargar, por ejemplo, "images/image01.png" usando:

    ImageIO.read(this.getClass().getResource("images/image01.png));

Pero sólo porque sé el nombre del archivo, por lo demás tengo que cargarlos dinámicamente.

OscarRyz avatar Sep 16 '09 02:09 OscarRyz
Aceptado
CodeSource src = MyClass.class.getProtectionDomain().getCodeSource();
if (src != null) {
  URL jar = src.getLocation();
  ZipInputStream zip = new ZipInputStream(jar.openStream());
  while(true) {
    ZipEntry e = zip.getNextEntry();
    if (e == null)
      break;
    String name = e.getName();
    if (name.startsWith("path/to/your/dir/")) {
      /* Do something with this entry. */
      ...
    }
  }
} 
else {
  /* Fail... */
}

Tenga en cuenta que en Java 7, puede crear un FileSystemarchivo JAR (zip) y luego utilizar los mecanismos de filtrado y recorrido por directorios de NIO para buscarlo. Esto facilitaría la escritura de código que maneje archivos JAR y directorios "explosionados".

erickson avatar Sep 15 '2009 19:09 erickson

Código que funciona tanto para archivos IDE como para archivos .jar:

import java.io.*;
import java.net.*;
import java.nio.file.*;
import java.util.*;
import java.util.stream.*;

public class ResourceWalker {
    public static void main(String[] args) throws URISyntaxException, IOException {
        URI uri = ResourceWalker.class.getResource("/resources").toURI();
        Path myPath;
        if (uri.getScheme().equals("jar")) {
            FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.<String, Object>emptyMap());
            myPath = fileSystem.getPath("/resources");
        } else {
            myPath = Paths.get(uri);
        }
        Stream<Path> walk = Files.walk(myPath, 1);
        for (Iterator<Path> it = walk.iterator(); it.hasNext();){
            System.out.println(it.next());
        }
    }
}
acheron55 avatar Jan 21 '2015 00:01 acheron55

La respuesta de Erickson funcionó perfectamente:

Aquí está el código de trabajo.

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

Y acabo de modificar mi método de carga a partir de esto:

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

A esto:

String  [] webimages = ...

BufferedImage image = ImageIO.read(this.getClass().getResource(webimages[nextIndex]));
OscarRyz avatar Sep 16 '2009 21:09 OscarRyz