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 con ".txt" del directorio "text_directory".
¿Cómo puedo leer el contenido de un directorio de manera 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 podría 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, podría 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 mismo puedo cargar, por ejemplo, "images / image01.png" usando:
ImageIO.read(this.getClass().getResource("images/image01.png));
Pero solo porque sé el nombre del archivo, para el resto tengo que cargarlos dinámicamente.
Respuestas:
Tenga en cuenta que en Java 7, puede crear un
FileSystem
archivo desde el archivo JAR (zip) y luego usar los mecanismos de filtrado y desplazamiento del directorio de NIO para buscarlo. Esto facilitaría la escritura de código que maneje archivos JAR y directorios "explotados".fuente
Código que funciona para archivos IDE y .jar:
fuente
FileSystems.newFileSystem()
toma unMap<String, ?>
, por lo que debe especificarCollections.emptyMap()
que debe devolver uno adecuadamente escrito. Esto funciona:Collections.<String, Object>emptyMap()
.fileSystem
!walk
métodoFiles
solo está disponible en 1.8). El único problema es que el directorio de recursos aparece en elFiles.walk(myPath, 1)
, no solo en los archivos. Supongo que el primer elemento puede simplemente ignorarsemyPath = fileSystem.getPath("/resources");
no funciona para mí; no encuentra nada. ¡Deberían ser "imágenes" en mi caso y el directorio de "imágenes" definitivamente está incluido en mi jar!La respuesta de Erickson funcionó perfectamente:
Aquí está el código de trabajo.
Y acabo de modificar mi método de carga a partir de esto:
A esto:
fuente
Me gustaría ampliar la respuesta de acheron55 , ya que es una solución muy poco segura, por varias razones:
FileSystem
objeto.FileSystem
objeto ya existe.Esta es una solución algo más segura:
No hay ninguna necesidad real de sincronizar sobre el nombre del archivo; uno podría simplemente sincronizar en el mismo objeto cada vez (o hacer el método
synchronized
), es puramente una optimización.Diría que esta sigue siendo una solución problemática, ya que podría haber otras partes en el código que usen la
FileSystem
interfaz sobre los mismos archivos y podría interferir con ellos (incluso en una aplicación de un solo subproceso).Además, no busca
null
s (por ejemplo, ongetClass().getResource()
.Esta interfaz Java NIO en particular es algo horrible, ya que introduce un recurso global / singleton no seguro para subprocesos, y su documentación es extremadamente vaga (muchas incógnitas debido a implementaciones específicas del proveedor). Los resultados pueden variar para otros
FileSystem
proveedores (no para JAR). Quizás haya una buena razón para que sea así; No lo sé, no he investigado las implementaciones.fuente
Suponiendo que su proyecto está empaquetado en un Jar (¡no necesariamente cierto!), Puede usar ClassLoader.getResource () o findResource () con el nombre de la clase (seguido de .class) para obtener el jar que contiene una clase determinada. Tendrá que analizar el nombre del jar de la URL que se devuelve (no es tan difícil), que dejaré como ejercicio para el lector :-)
Asegúrese de probar el caso en el que la clase no sea parte de un frasco.
fuente
CodeSource
.Me he portado respuesta de acheron55 a Java 7 y cerré el
FileSystem
objeto. Este código funciona en IDE, en archivos jar y en un jar dentro de una guerra en Tomcat 7; pero tenga en cuenta que no funciona en un frasco dentro de una guerra en JBoss 7 (daFileSystemNotFoundException: Provider "vfs" not installed
, vea también esta publicación ). Además, como el código original, no es seguro para subprocesos, como sugiere errr . Por estas razones he abandonado esta solución; sin embargo, si puede aceptar estos problemas, aquí está mi código listo para usar:fuente
Aquí hay un método que escribí para "ejecutar todos los JUnits en un paquete". Debería poder adaptarlo a sus necesidades.
Editar: Ah, en ese caso, es posible que también desee este fragmento (mismo caso de uso :))
fuente
Aquí hay un ejemplo del uso de la biblioteca Reflections para escanear de forma recursiva classpath por patrón de nombre de expresión regular aumentado con un par de ventajas de Guava para recuperar el contenido de los recursos:
Esto funciona tanto con jarras como con clases explosionadas.
fuente
Un archivo jar es solo un archivo zip con un manifiesto estructurado. Puede abrir el archivo jar con las herramientas habituales de java zip y escanear el contenido del archivo de esa manera, inflar secuencias, etc. Luego úselo en una llamada getResourceAsStream, y debería ser todo perfecto.
EDITAR / después de la aclaración
Me tomó un minuto recordar todos los detalles y estoy seguro de que hay formas más limpias de hacerlo, pero quería ver que no estaba loco. En mi proyecto, image.jpg es un archivo en alguna parte del archivo jar principal. Obtengo el cargador de clases de la clase principal (SomeClass es el punto de entrada) y lo uso para descubrir el recurso image.jpg. Luego, algo de magia de flujo para meterlo en este elemento ImageInputStream y todo está bien.
fuente
new File("blah.JAR")
para crear un objeto Archivo que represente el JAR, por ejemplo. Simplemente reemplace "blah.JAR" con el nombre de su JAR.Dado un archivo JAR real, puede enumerar el contenido usando
JarFile.entries()
. Sin embargo, necesitará saber la ubicación del archivo JAR; no puede simplemente pedirle al cargador de clases que enumere todo lo que puede encontrar.Debería poder calcular la ubicación del archivo JAR en función de la URL devuelta
ThisClassName.class.getResource("ThisClassName.class")
, pero puede ser un poco complicado.fuente
new File("baz.jar)
, el objeto File representaría su archivo JAR.Hace algún tiempo hice una función que obtiene clases desde dentro de JAR:
fuente
fuente
Hay dos utilidades muy útiles, ambas llamadas JarScan:
www.inetfeedback.com/jarscan
jarscan.dev.java.net
Vea también esta pregunta: JarScan, escanee todos los archivos JAR en todas las subcarpetas para una clase específica
fuente
El mecanismo más robusto para enumerar todos los recursos en la ruta de clases es actualmente usar este patrón con ClassGraph , porque maneja la más amplia gama posible de mecanismos de especificación de rutas de clases , incluido el nuevo sistema de módulos JPMS. (Soy el autor de ClassGraph.)
También hay muchas otras formas de gestionar los recursos .
fuente
Solo una forma diferente de enumerar / leer archivos de una URL de jar y lo hace de forma recursiva para jarras anidadas
https://gist.github.com/trung/2cd90faab7f75b3bcbaa
fuente
Uno más para el camino:
Esto es un poco más flexible para hacer coincidir nombres de archivos específicos porque usa comodines globbing.
Un estilo más funcional:
fuente