fileName
あなたが渡しているがどのように解釈されるかについては、微妙な違いがあります。基本的に、 と の 2 つの異なる方法がClassLoader.getResourceAsStream()
ありClass.getResourceAsStream()
ます。これら 2 つの方法では、リソースの検索方法が異なります。
ではClass.getResourceAsStream(path)
、パスは、呼び出し元のクラスのパッケージに対してローカルなパスとして解釈されます。たとえば、 を呼び出すとString.class.getResourceAsStream("myfile.txt")
、次の場所にあるクラスパス内のファイルが検索されます"java/lang/myfile.txt"
。パスが で始まる場合/
、絶対パスと見なされ、クラスパスのルートから検索が開始されます。したがって、呼び出しString.class.getResourceAsStream("/myfile.txt")
はクラスパスの次の場所を調べます./myfile.txt
。
ClassLoader.getResourceAsStream(path)
すべてのパスを絶対パスと見なします。したがって、 と を呼び出すString.class.getClassLoader().getResourceAsStream("myfile.txt")
とString.class.getClassLoader().getResourceAsStream("/myfile.txt")
、クラスパスの次の場所にあるファイルが検索されます./myfile.txt
。
この投稿で場所について言及するたびに、それは、リソースをロードする Class や ClassLoader に応じて、ファイルシステム自体または対応する jar ファイル内の場所である可能性があります。
あなたの場合、アプリケーションサーバーからクラスをロードしているので、Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)
代わりにthis.getClass().getClassLoader().getResourceAsStream(fileName)
. this.getClass().getResourceAsStream()
も機能します。
その特定の問題の詳細については、この記事をお読みください。
Tomcat 7 以前のユーザーへの警告
この質問に対する回答の 1 つは、私の説明が Tomcat 7 に対して正しくないように思われることを示しています。
WebAppClassLoader
そこで、Tomcat のいくつかのバージョンについて、Tomcat のソース コードを調べました。の実装findResource(String name)
(要求されたリソースへの URL の生成を最終的に担当する) は、Tomcat 6 と Tomcat 7 で実質的に同じですが、Tomcat 8 では異なります。
バージョン 6 および 7 では、実装はリソース名の正規化を試みません。これは、これらのバージョンでclassLoader.getResourceAsStream("/resource.txt")
は、イベントと同じ結果を生成するclassLoader.getResourceAsStream("resource.txt")
必要があるにもかかわらず、生成しない可能性があることを意味します (Javadoc で指定されているため)。[ソースコード]
ただし、バージョン 8 では、リソース名の絶対バージョンが使用されることを保証するために、リソース名が正規化されます。したがって、Tomcat 8 では、上記の 2 つの呼び出しは常に同じ結果を返す必要があります。[ソースコード]
そのため、8 より前のバージョンの Tomcat を使用する場合は特に注意する必要があります。また、実際に呼び出すことにも注意する必要がありClassLoader.getResourceAsStream()
ます(先頭が削除されます)。Class.getResourceAsStream()
class.getResourceAsStream("/resource.txt")
classLoader.getResourceAsStream("resource.txt")
/