J'ai ce code qui lit tous les fichiers d'un répertoire.
File textFolder = new File("text_directory");
File [] texFiles = textFolder.listFiles( new FileFilter() {
public boolean accept( File file ) {
return file.getName().endsWith(".txt");
}
});
Cela fonctionne très bien. Il remplit le tableau avec tous les fichiers qui se terminent par ".txt" du répertoire "text_directory".
Comment puis-je lire le contenu d'un répertoire de la même manière dans un fichier JAR?
Donc, ce que je veux vraiment faire, c'est lister toutes les images dans mon fichier JAR, afin que je puisse les charger avec:
ImageIO.read(this.getClass().getResource("CompanyLogo.png"));
(Celui-ci fonctionne car le "CompanyLogo" est "codé en dur" mais le nombre d'images à l'intérieur du fichier JAR peut être de 10 à 200 de longueur variable.)
ÉDITER
Donc, je suppose que mon problème principal serait: Comment connaître le nom du fichier JAR où vit ma classe principale?
Certes, je pouvais le lire en utilisant java.util.Zip
.
Ma structure est comme ceci:
Ils sont comme:
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
À l'heure actuelle, je suis capable de charger par exemple "images / image01.png" en utilisant:
ImageIO.read(this.getClass().getResource("images/image01.png));
Mais seulement parce que je connais le nom du fichier, pour le reste je dois les charger dynamiquement.
Réponses:
Notez que dans Java 7, vous pouvez créer un
FileSystem
fichier à partir du fichier JAR (zip), puis utiliser les mécanismes de navigation et de filtrage de répertoire de NIO pour le parcourir. Cela faciliterait l'écriture de code qui gère les JAR et les répertoires «éclatés».la source
Code qui fonctionne pour les fichiers IDE et .jar:
la source
FileSystems.newFileSystem()
prend unMap<String, ?>
, vous devez donc spécifierCollections.emptyMap()
qu'il doit en renvoyer un correctement typé. Cela fonctionne:Collections.<String, Object>emptyMap()
.fileSystem
!walk
méthode dansFiles
est uniquement disponible dans la version 1.8). Le seul problème est que le répertoire des ressources apparaît dans leFiles.walk(myPath, 1)
, pas seulement les fichiers. Je suppose que le premier élément peut être simplement ignorémyPath = fileSystem.getPath("/resources");
ne fonctionne pas pour moi; il ne trouve rien. Cela devrait être "images" dans mon cas et le répertoire "images" est définitivement inclus dans mon pot!La réponse d' Erickson a parfaitement fonctionné:
Voici le code de travail.
Et je viens de modifier ma méthode de chargement à partir de ceci:
Pour ça:
la source
Je voudrais développer la réponse de acheron55 , car il s'agit d'une solution très peu sûre, pour plusieurs raisons:
FileSystem
objet.FileSystem
objet existe déjà.C'est une solution un peu plus sûre:
Il n'y a pas vraiment besoin de synchroniser le nom du fichier; on pourrait simplement se synchroniser sur le même objet à chaque fois (ou faire la méthode
synchronized
), c'est purement une optimisation.Je dirais que c'est toujours une solution problématique, car il peut y avoir d'autres parties du code qui utilisent l'
FileSystem
interface sur les mêmes fichiers, et cela pourrait interférer avec eux (même dans une seule application threadée).De plus, il ne vérifie pas les
null
s (par exemple, ongetClass().getResource()
.Cette interface Java NIO particulière est plutôt horrible, car elle introduit une ressource globale / singleton non thread-safe, et sa documentation est extrêmement vague (beaucoup d'inconnues dues aux implémentations spécifiques du fournisseur). Les résultats peuvent varier pour d'autres
FileSystem
fournisseurs (pas pour JAR). Il y a peut-être une bonne raison à cela; Je ne sais pas, je n'ai pas recherché les implémentations.la source
En supposant que votre projet est emballé dans un Jar (pas nécessairement vrai!), Vous pouvez utiliser ClassLoader.getResource () ou findResource () avec le nom de la classe (suivi de .class) pour obtenir le fichier jar qui contient une classe donnée. Vous devrez analyser le nom du fichier à partir de l'URL renvoyée (pas si difficile), que je laisserai comme exercice au lecteur :-)
Assurez-vous de tester le cas où la classe ne fait pas partie d'un pot.
la source
CodeSource
.J'ai porté la réponse d' acheron55 sur Java 7 et fermé l'
FileSystem
objet. Ce code fonctionne dans les IDE, dans les fichiers jar et dans un jar à l'intérieur d'une guerre sur Tomcat 7; mais notez que ça ne marche pas dans un bocal à l'intérieur d'une guerre sur JBoss 7 (ça donneFileSystemNotFoundException: Provider "vfs" not installed
, voir aussi ce post ). De plus, comme le code original, il n'est pas thread-safe, comme suggéré par errr . Pour ces raisons, j'ai abandonné cette solution; cependant, si vous pouvez accepter ces problèmes, voici mon code prêt à l'emploi:la source
Voici une méthode que j'ai écrite pour "exécuter tous les JUnits sous un package". Vous devriez pouvoir l'adapter à vos besoins.
Edit: Ah, dans ce cas, vous voudrez peut-être aussi cet extrait (même cas d'utilisation :))
la source
Voici un exemple d'utilisation de la bibliothèque Reflections pour analyser de manière récursive le chemin de classe par modèle de nom regex augmenté de quelques avantages Guava pour récupérer le contenu des ressources:
Cela fonctionne avec les bocaux et les classes éclatées.
la source
Un fichier jar est juste un fichier zip avec un manifeste structuré. Vous pouvez ouvrir le fichier jar avec les outils java zip habituels et analyser le contenu du fichier de cette façon, gonfler les flux, etc.
EDIT / après clarification
Il m'a fallu une minute pour me souvenir de tous les éléments et je suis sûr qu'il existe des moyens plus propres de le faire, mais je voulais voir que je n'étais pas fou. Dans mon projet, image.jpg est un fichier dans une partie du fichier jar principal. J'obtiens le chargeur de classe de la classe principale (SomeClass est le point d'entrée) et l'utilise pour découvrir la ressource image.jpg. Ensuite, un peu de magie de flux pour l'introduire dans cette chose ImageInputStream et tout va bien.
la source
new File("blah.JAR")
pour créer un objet File qui représente le JAR, par exemple. Remplacez simplement "blah.JAR" par le nom de votre JAR.Étant donné un fichier JAR réel, vous pouvez répertorier le contenu à l'aide de
JarFile.entries()
. Cependant, vous aurez besoin de connaître l'emplacement du fichier JAR - vous ne pouvez pas simplement demander au chargeur de classe de répertorier tout ce qu'il pourrait atteindre.Vous devriez être en mesure de déterminer l'emplacement du fichier JAR en fonction de l'URL renvoyée
ThisClassName.class.getResource("ThisClassName.class")
, mais cela peut être un peu compliqué.la source
new File("baz.jar)
, l'objet File représenterait votre fichier JAR.Il y a quelque temps, j'ai créé une fonction qui obtient des classes à partir de JAR:
la source
la source
Il existe deux utilitaires très utiles appelés JarScan:
www.inetfeedback.com/jarscan
jarscan.dev.java.net
Voir aussi cette question: JarScan, scannez tous les fichiers JAR dans tous les sous-dossiers pour une classe spécifique
la source
Le mécanisme le plus robuste pour lister toutes les ressources dans le chemin de classe consiste actuellement à utiliser ce modèle avec ClassGraph , car il gère le plus large éventail possible de mécanismes de spécification de chemin de classe, y compris le nouveau système de module JPMS. (Je suis l'auteur de ClassGraph.)
Il existe également de nombreuses autres façons de gérer les ressources .
la source
Juste une manière différente de lister / lire des fichiers à partir d'une URL de jar et il le fait de manière récursive pour les jars imbriqués
https://gist.github.com/trung/2cd90faab7f75b3bcbaa
la source
Un de plus pour la route:
C'est un peu plus flexible pour faire correspondre des noms de fichiers spécifiques car il utilise le globbing générique.
Un style plus fonctionnel:
la source