Il existe des différences subtiles quant à la façon dont fileName
vous passez est interprété. Fondamentalement, vous avez 2 méthodes différentes: ClassLoader.getResourceAsStream()
etClass.getResourceAsStream()
. Ces deux méthodes localiseront la ressource différemment.
Dans Class.getResourceAsStream(path)
, le chemin d'accès est interprété comme un chemin d'accès local au package de la classe à partir de laquelle vous l'appelez. Par exemple appel, String.getResourceAsStream("myfile.txt")
va chercher un fichier dans votre classpath à l'adresse suivante: "java/lang/myfile.txt"
. Si votre chemin commence par un /
, il sera alors considéré comme un chemin absolu et commencera la recherche à partir de la racine du chemin de classe. Ainsi, l'appel String.getResourceAsStream("/myfile.txt")
se penchera sur l'emplacement suivant dans votre chemin de classe ./myfile.txt
.
ClassLoader.getResourceAsStream(path)
considérera tous les chemins comme des chemins absolus. Donc , appeler String.getClassLoader().getResourceAsStream("myfile.txt")
et String.getClassLoader().getResourceAsStream("/myfile.txt")
sera à la fois regarder un fichier dans votre classpath à l'adresse suivante: ./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 à l'intérieur du fichier jar correspondant, en fonction de la classe et / ou du ClassLoader à partir desquels vous chargez la ressource.
Dans votre cas, vous chargez la classe à partir d'un serveur d'applications, vous devez donc l'utiliser à la Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)
place de this.getClass().getClassLoader().getResourceAsStream(fileName)
. this.getClass().getResourceAsStream()
fonctionnera également.
Lisez cet article pour des informations plus détaillées sur ce problème particulier.
Avertissement pour les utilisateurs de Tomcat 7 et inférieurs
L'une des réponses à cette question indique que mon explication semble incorrecte pour Tomcat 7. J'ai essayé de regarder autour de moi pour voir 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 ultimement responsable de la production de l'URL de la ressource demandée) est pratiquement identique dans Tomcat 6 et Tomcat 7, mais est différente dans Tomcat 8.
Dans les versions 6 et 7, l'implémentation n'essaie pas de normaliser le nom de la ressource. Cela signifie que dans ces versions, il se classLoader.getResourceAsStream("/resource.txt")
peut qu'il ne produise pas le même résultat que l' classLoader.getResourceAsStream("resource.txt")
événement (car c'est ce que spécifie le Javadoc). [code source]
Cependant, dans la version 8, le nom de la ressource est normalisé pour garantir que la version absolue du nom de la ressource est celle utilisée. Par conséquent, dans Tomcat 8, les deux appels décrits ci-dessus doivent toujours renvoyer le même résultat. [code source]
Par conséquent, vous devez être extrêmement prudent lorsque vous utilisez ClassLoader.getResourceAsStream()
ou Class.getResourceAsStream()
sur des versions de Tomcat antérieures à 8. Et vous devez également garder à l'esprit que les class.getResourceAsStream("/resource.txt")
appels sont réellement effectués classLoader.getResourceAsStream("resource.txt")
(le début /
est supprimé).
getClass().getResourceAsStream("/myfile.txt")
se comporte différemment degetClassLoader().getResourceAsStream("/myfile.txt")
.