1. ホーム

[解決済み】InputStreamとしてファイルを読み込むさまざまな方法

2022-04-17 12:14:36

質問

の違いは何ですか?

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にデプロイされています。

解決方法は?

をどのように使用するかについては、微妙な違いがあります。 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 .

この投稿で場所について言及するときはいつも、リソースをロードするクラスやClassLoaderに応じて、ファイルシステム自体または対応するjarファイル内の場所である可能性があります。

あなたの場合、アプリケーションサーバーからクラスを読み込んでいるので Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName) ではなく this.getClass().getClassLoader().getResourceAsStream(fileName) . this.getClass().getResourceAsStream() も動作します。

読む この記事 をクリックすると、その問題についての詳細な情報が得られます。


Tomcat7以下をお使いの方へのご注意

この質問に対する回答の中に、私の説明がTomcat7では間違っているようだと書かれています。 なぜそうなるのか、いろいろと調べてみました。

そこで、ソースコードを見てみると、Tomcatの WebAppClassLoader は、いくつかのバージョンの 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つの呼び出しは常に同じ結果を返すはずです。 [ソースコード]

そのため、以下のような場合、特に注意が必要です。 ClassLoader.getResourceAsStream() または Class.getResourceAsStream() また、8より前のバージョンのTomcatでは class.getResourceAsStream("/resource.txt") 実際には classLoader.getResourceAsStream("resource.txt") (先頭の / は取り除かれます)。