157 votes

Comment puis-je accéder à un dossier à l'intérieur d'un dossier de ressources à partir de mon fichier jar ?

J'ai un dossier/package de ressources à la racine de mon projet, je ne veux pas charger un certain fichier. Si je voulais charger un certain fichier, j'utiliserais class.getResourceAsStream et tout irait bien ! Ce que je veux faire en fait, c'est charger un "Dossier" à l'intérieur du dossier des ressources, boucler sur les fichiers à l'intérieur de ce dossier et obtenir un flux pour chaque fichier et lire le contenu... Supposons que les noms de fichiers ne soient pas déterminés avant l'exécution... Que dois-je faire ? Existe-t-il un moyen d'obtenir une liste des fichiers contenus dans un dossier dans votre fichier jar ? Remarquez que le fichier Jar contenant les ressources est le même que celui à partir duquel le code est exécuté...

1 votes

0 votes

5 votes

La première concerne l'extraction d'un fichier jar, ce qui est en quelque sorte la dernière chose que je veux essayer, comme une situation de type "si le pire arrive" ! Si je veux extraire les fichiers, je les mettrais simplement dans mon dossier d'installation au moment de l'installation ! Je veux y accéder depuis l'intérieur du jar, et ma raison est que, si getResourceAsStream peut accéder à un fichier, Java devrait également être capable d'explorer les dossiers dans ce jar, sans avoir besoin de l'extraire ! Mais merci...

120voto

user1079877 Points 703

Enfin, j'ai trouvé la solution :

final String path = "sample/folder";
final File jarFile = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath());

if(jarFile.isFile()) {  // Run with JAR file
    final JarFile jar = new JarFile(jarFile);
    final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
    while(entries.hasMoreElements()) {
        final String name = entries.nextElement().getName();
        if (name.startsWith(path + "/")) { //filter according to the path
            System.out.println(name);
        }
    }
    jar.close();
} else { // Run with IDE
    final URL url = Launcher.class.getResource("/" + path);
    if (url != null) {
        try {
            final File apps = new File(url.toURI());
            for (File app : apps.listFiles()) {
                System.out.println(app);
            }
        } catch (URISyntaxException ex) {
            // never happens
        }
    }
}

Le deuxième bloc ne fonctionne que lorsque vous exécutez l'application sur l'IDE (pas avec le fichier jar), vous pouvez le supprimer si vous n'aimez pas cela.

0 votes

Mise à jour de la réponse correcte. Bien que ce ne soit pas ce que je voudrais faire, surtout dans un code comportant plus de 34000 fichiers sources... Mais cela semble être la seule solution. Merci.

4 votes

Pour info, cela ne fonctionne pas si on le lance depuis webstart car getPath renvoie quelque chose de relatif au domaine du serveur.

2 votes

Je ne pense pas que cela va fonctionner si le chemin est dans un jar, il donnera cette erreur sur la conversion toURI : java.lang.IllegalArgumentException : L'URI n'est pas hiérarchique

11voto

Glen Best Points 11455

Essayez ce qui suit.
Faire le chemin des ressources "<PathRelativeToThisClassFile>/<ResourceDirectory>" Par exemple, si le chemin de votre classe est com.abc.package.MyClass et que vos fichiers de ressources se trouvent dans src/com/abc/package/resources/ :

URL url = MyClass.class.getResource("resources/");
if (url == null) {
     // error - missing folder
} else {
    File dir = new File(url.toURI());
    for (File nextFile : dir.listFiles()) {
        // Do something with nextFile
    }
}

Vous pouvez également utiliser

URL url = MyClass.class.getResource("/com/abc/package/resources/");

34 votes

Merci pour votre temps et vos efforts, mais cela ne fonctionne PAS lorsque votre code de base se trouve dans un fichier .jar et que vos ressources se trouvent également dans ce fichier .jar. Lorsque vous êtes à l'intérieur d'un fichier .jar, vous ne pouvez pas créer un File() et vous ne pouvez pas non plus obtenir une URL pour ce dossier... Personnellement, je m'en suis accommodé et j'ai simplement listé chaque fichier dans un XML... Je ne pense pas que vous puissiez faire cela pour un dossier à l'intérieur d'un fichier jar...

2 votes

Désolé que vous ayez des problèmes. Cependant, cela fonctionne réellement lorsque votre base de code est dans un fichier jar et que vos ressources sont également dans ce fichier jar. Vous ne créez pas un File() sur le disque - vous lisez le fichier dans le fichier jar dans la mémoire java. Notez que le ClassLoader est très heureux de traiter un fichier jar comme un répertoire sur le disque. Voici les détails de la source :

0 votes

Thread.currentThread().getContextClassLoader().getResource( "Hello.txt" ) ;

-2voto

Peter Kriens Points 6632

C'est simple... utilisez OSGi. Dans OSGi, vous pouvez itérer sur les entrées de votre Bundle avec findEntries et findPaths.

14 votes

Si cela implique OSGI, je ne peux pas dire que ce soit "simple". Mais s'il se trouve que vous utilisez déjà OSGI... oui, bien sûr. Mais suggérer de passer à OSGI juste pour résoudre ce problème particulier semble un peu exagéré.

0 votes

OSGi résout également de nombreux autres problèmes et il est aujourd'hui très facile de s'y mettre. Voir les tutoriels OSGi enRoute

0 votes

Je m'éloignerais d'OSGi à moins que vous ne soyez déjà obligé de l'utiliser. C'est un Bloatware surdimensionné qui résout les problèmes de déploiement des années 90.

-3voto

Renato Points 45
File file = new File("newname.ext");
if (!file.exists()) {
    InputStream link = (getClass().getResourceAsStream("/pack/resources/filename.ext"));
    Files.copy(link, file.getAbsoluteFile().toPath());
}

-28voto

James Anderson Points 18253

Ce site lien vous explique comment.

La magie réside dans la méthode getResourceAsStream() :

InputStream is = 
this.getClass().getClassLoader().getResourceAsStream("yourpackage/mypackage/myfile.xml")

22 votes

Non, mec ! Je ne veux pas un seul dossier ! Je veux un dossier entier, dont les sous-fichiers sont indéterminés avant le lancement ! !!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X