Il existe des différences subtiles quant à la manière dont les fileName
que vous passez est interprété. En fait, vous avez deux méthodes différentes : ClassLoader.getResourceAsStream()
y Class.getResourceAsStream()
. Ces deux méthodes permettent de localiser la ressource de manière différente.
En Class.getResourceAsStream(path)
le chemin est interprété comme un chemin local au paquetage de la classe à partir de laquelle vous l'appelez. Par exemple, appeler, String.class.getResourceAsStream("myfile.txt")
cherchera un fichier dans votre classpath à l'emplacement suivant : "java/lang/myfile.txt"
. Si votre chemin commence par un /
alors il sera considéré comme un chemin absolu, et commencera la recherche à partir de la racine du classpath. Ainsi, appeler String.class.getResourceAsStream("/myfile.txt")
cherchera l'emplacement suivant dans votre chemin de classe ./myfile.txt
.
ClassLoader.getResourceAsStream(path)
considérera que tous les chemins sont des chemins absolus. Ainsi, appeler String.class.getClassLoader().getResourceAsStream("myfile.txt")
y String.class.getClassLoader().getResourceAsStream("/myfile.txt")
chercheront tous deux un fichier dans votre classpath à l'emplacement suivant : ./myfile.txt
.
Chaque fois que je mentionne un emplacement dans cet article, il peut s'agir d'un emplacement dans votre système de fichiers lui-même, ou dans le fichier jar correspondant, en fonction de la classe et/ou du ClassLoader à partir duquel vous chargez la ressource.
Dans votre cas, vous chargez la classe à partir d'un serveur d'application, vous devez donc utiliser la méthode suivante Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)
au lieu de this.getClass().getClassLoader().getResourceAsStream(fileName)
. this.getClass().getResourceAsStream()
fonctionnera également.
Lire cet article pour obtenir des informations plus détaillées sur ce problème particulier.
Avertissement pour les utilisateurs de Tomcat 7 et moins
L'une des réponses à cette question indique que mon explication semble être incorrecte pour Tomcat 7. J'ai essayé de chercher pourquoi ce serait le cas.
J'ai donc regardé le code source de Tomcat. WebAppClassLoader
pour plusieurs versions de Tomcat. L'implémentation de findResource(String name)
(qui est utilement responsable de la production de l'URL de la ressource demandée) est pratiquement identique dans Tomcat 6 et Tomcat 7, mais est différent dans Tomcat 8.
Dans les versions 6 et 7, l'implémentation ne tente pas de normaliser le nom de la ressource. Cela signifie que dans ces versions, classLoader.getResourceAsStream("/resource.txt")
peut ne pas produire le même résultat que classLoader.getResourceAsStream("resource.txt")
alors qu'il le devrait (puisque c'est ce que spécifie la Javadoc). [code source]
Dans la version 8 cependant, le nom de la ressource est normalisé pour garantir que la version absolue du nom de la ressource est celle qui est utilisée. Par conséquent, dans Tomcat 8, les deux appels décrits ci-dessus devraient toujours retourner le même résultat. [code source]
Par conséquent, vous devez être très prudent lorsque vous utilisez ClassLoader.getResourceAsStream()
o Class.getResourceAsStream()
sur les versions de Tomcat antérieures à 8. Et vous devez également garder à l'esprit que class.getResourceAsStream("/resource.txt")
appelle effectivement classLoader.getResourceAsStream("resource.txt")
(le chef de file /
est supprimée).