265 votes

getResourceAsStream renvoie null

Je charge un fichier texte à partir d'un paquet dans un JAR compilé de mon projet Java. La structure du répertoire concerné est la suivante :

/src/initialization/Lifepaths.txt

Mon code charge un fichier en appelant Class::getResourceAsStream pour renvoyer un InputStream .

public class Lifepaths {
    public static void execute() {
        System.out.println(Lifepaths.class.getClass().
            getResourceAsStream("/initialization/Lifepaths.txt"));
    }

    private Lifepaths() {}

    //This is temporary; will eventually be called from outside
    public static void main(String[] args) {execute();}
}

L'impression se fera toujours null peu importe ce que j'utilise. Je ne sais pas pourquoi ce qui précède ne fonctionne pas, j'ai donc également essayé :

  • "/src/initialization/Lifepaths.txt"
  • "initialization/Lifepaths.txt"
  • "Lifepaths.txt"

Aucun des deux ne fonctionne. J'ai lire nombreux questions jusqu'à présent sur le sujet, mais aucune d'entre elles n'a été utile - en général, elles disent simplement de charger les fichiers en utilisant le chemin Root, ce que je fais déjà. Cela, ou simplement charger le fichier à partir du répertoire courant (juste load filename ), que j'ai également essayé. Le fichier est compilé dans le JAR à l'emplacement approprié avec le nom approprié.

Comment puis-je résoudre ce problème ?

235voto

hoaz Points 3618

Lifepaths.class.getClass().getResourceAsStream(...) charge les ressources en utilisant le chargeur de classe du système, il échoue évidemment parce qu'il ne voit pas vos JARs

Lifepaths.class.getResourceAsStream(...) charge les ressources en utilisant le même chargeur de classe que celui qui a chargé la classe Lifepaths et il devrait avoir accès aux ressources de vos JARs

72voto

Puce Points 13540

Les règles sont les suivantes :

  1. vérifier l'emplacement du fichier que vous voulez charger à l'intérieur du JAR (et donc s'assurer qu'il a bien été ajouté au JAR)
  2. utiliser soit un chemin absolu : le chemin commence à la racine du JAR
  3. utiliser un chemin relatif : le chemin commence au répertoire du paquetage de la classe que vous appelez getResource/ getResoucreAsStream

Et essayez :

Lifepaths.class.getResourceAsStream("/initialization/Lifepaths.txt")

au lieu de

Lifepaths.class.getClass().getResourceAsStream("/initialization/Lifepaths.txt")

(je ne sais pas si cela fait une différence, mais la première utilisera le bon ClassLoader/ JAR, alors que je ne suis pas sûr de la seconde).

60voto

greedybuddha Points 4904

Il y a donc plusieurs façons d'obtenir une ressource à partir d'un jar et chacune a une syntaxe légèrement différente où le chemin doit être spécifié différemment.

La meilleure explication que j'ai vue est cet article de InfoWorld . Je vais résumer ici, mais si vous voulez en savoir plus, vous devriez consulter l'article.

Méthodes

  1. ClassLoader.getResourceAsStream() .

Format : Noms séparés par "/" ; pas de "/" en tête (tous les noms sont absolus).

Exemple : this.getClass().getClassLoader().getResourceAsStream("some/pkg/resource.properties");

  1. Class.getResourceAsStream()

Format : Noms séparés par "/" ; le premier "/" indique des noms absolus ; tous les autres noms sont relatifs au paquetage de la classe.

Exemple : this.getClass().getResourceAsStream("/some/pkg/resource.properties");

Mis à jour en septembre 2020 : Changement du lien de l'article. L'article original provenait de Javaworld, il est maintenant hébergé sur InfoWorld (et comporte beaucoup plus de publicités).

24voto

Shijing Lv Points 147

Grosso modo :

getClass().getResource("/") ~= Thread.currentThread().getContextClassLoader().getResource(".")

Supposons que la structure de votre projet soit la suivante :

 src
    main
    test
        java
           com
               github
                   xyz
                       proj
                           MainTest.java
                           TestBase.java
        resources
            abcd.txt
 target
     test-classes  <-- this.getClass.getResource("/")
                      `--Thread.currentThread().getContextClassLoader().getResources(".")
         com
            github
                xyz
                    proj  <-- this.getClass.getResource(".")
                        MainTest.class
                        TestBase.class
         resources
             abcd.txt

// in MainTest.java
this.getClass.getResource("/") -> "~/proj_dir/target/test-classes/"
this.getClass.getResource(".") -> "~/proj_dir/target/test-classes/com/github/xyz/proj/"
Thread.currentThread().getContextClassLoader().getResources(".") -> "~/proj_dir/target/test-classes/"
Thread.currentThread().getContextClassLoader().getResources("/") ->  null

15voto

Paul Smith Points 15

N'utilisez pas de chemins absolus, mais des chemins relatifs au répertoire "resources" de votre projet. Un code simple et rapide qui affiche le contenu de MyTest.txt dans le répertoire 'resources'.

@Test
public void testDefaultResource() {
    // can we see default resources
    BufferedInputStream result = (BufferedInputStream) 
         Config.class.getClassLoader().getResourceAsStream("MyTest.txt");
    byte [] b = new byte[256];
    int val = 0;
    String txt = null;
    do {
        try {
            val = result.read(b);
            if (val > 0) {
                txt += new String(b, 0, val);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } 
    } while (val > -1);
    System.out.println(txt);
}

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