232

次の違いは何ですか:

InputStream is = this.getClass().getClassLoader().getResourceAsStream(fileName)

InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)

InputStream is = this.getClass().getResourceAsStream(fileName)

それぞれが他のものよりも使用するのに適しているのはいつですか?

読み取りたいファイルは、ファイルを読み取るクラスとしてクラスパスにあります。私のクラスとファイルは同じ jar にあり、EAR ファイルにパッケージ化され、WebSphere 6.1 にデプロイされています。

4

6 に答える 6

303

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")/

于 2009-03-24T05:52:21.640 に答える
21

MyClass.class.getClassLoader().getResourceAsStream(path)コードに関連付けられたリソースをロードするために使用します。MyClass.class.getResourceAsStream(path)ショートカットとして、およびクラスのパッケージ内にパッケージ化されたリソースに使用します。

Thread.currentThread().getContextClassLoader().getResourceAsStream(path)呼び出し元のコードに厳密にバインドされていない、クライアント コードの一部であるリソースを取得するために使用します。スレッド コンテキスト クラス ローダーが何かを指している可能性があるため、これには注意する必要があります。

于 2009-03-24T11:57:39.330 に答える
4

ここにあるこれらすべての回答と、この質問の回答は、「/foo/bar.properties」のような絶対 URL の読み込みが と で同じように扱われることを示唆していclass.getResourceAsStream(String)ますclass.getClassLoader().getResourceAsStream(String)。これは、少なくとも私の Tomcat 構成/バージョン (現在 7.0.40) では当てはまりません。

MyClass.class.getResourceAsStream("/foo/bar.properties"); // works!  
MyClass.class.getClassLoader().getResourceAsStream("/foo/bar.properties"); // does NOT work!

申し訳ありませんが、満足のいく説明はまったくありませんが、Tomcat がクラスローダーで汚いトリックと彼の黒魔術を行い、違いを引き起こしていると思います。以前からずっと使用class.getResourceAsStream(String)していますが、特に問題はありません。

PS:こちらにも投稿しました

于 2013-11-19T11:02:54.773 に答える
-4

それは動作します、これを試してください:

InputStream in_s1 =   TopBrandData.class.getResourceAsStream("/assets/TopBrands.xml");
于 2014-07-02T08:21:19.133 に答える