¿Cómo enumerar los archivos dentro de un archivo JAR?
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.
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 FileSystem
archivo 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".
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());
}
}
}
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]));