webapp でファイルをロードしようとしていて、FileNotFound
使用すると例外が発生しましたFileInputStream
。ただし、同じパスを使用して、ファイルを読み込んだときにファイルを読み込むことができましたgetResourceAsStream()
。2 つの方法の違いは何ですか? また、一方が機能し、他方が機能しないのはなぜですか?
6 に答える
java.io.File
および コンソートは、ローカル ディスク ファイル システムで動作します。問題の根本的な原因は、相対パスjava.io
が現在の作業ディレクトリに依存していることです。つまり、JVM(あなたの場合:Webサーバーのもの)が開始されるディレクトリです。これは、たとえば、C:\Tomcat\bin
またはまったく異なるものである可能性がありますが、したがって、そうではない C:\Tomcat\webapps\contextname
か、またはあなたが期待するものではありません. 通常の Eclipse プロジェクトでは、C:\Eclipse\workspace\projectname
. 現在の作業ディレクトリについては、次の方法で知ることができます。
System.out.println(new File(".").getAbsolutePath());
ただし、作業ディレクトリをプログラムで制御することはできません。API では、相対パスではなく絶対パスを使用することをお勧めします。File
例C:\full\path\to\file.ext
。
Java (Web) アプリケーションで絶対パスをハードコードしたり、推測したりしたくありません。これは単なる移植性の問題です (つまり、システム X では動作しますが、システム Y では動作しません)。通常の方法では、これらの種類のリソースをclasspathに配置するか、そのフル パスをクラスパスに追加します (Eclipse などの IDE では、src
それぞれフォルダーと「ビルド パス」になります)。このようにして、ClassLoader
by ClassLoader#getResource()
またはを使用してそれらを取得できますClassLoader#getResourceAsStream()
。偶然にもわかったように、クラスパスの「ルート」に関連するファイルを見つけることができます。Web アプリケーション (または複数のクラスローダーを使用するその他のアプリケーション) では、このためClassLoader
に返される asを使用することをお勧めします。これにより、Web アプリケーションThread.currentThread().getContextClassLoader()
コンテキストの「外側」も確認できます。
webapps のもう 1 つの代替手段は、ServletContext#getResource()
とそれに対応するServletContext#getResourceAsStream()
です。web
フォルダーを含む、webapp プロジェクトの public フォルダーにあるファイルにアクセスでき/WEB-INF
ます。はServletContext
継承されたgetServletContext()
メソッドによってサーブレットで使用でき、そのまま呼び出すことができます。
以下も参照してください。
getResourceAsStream
(すでに学んだように)Webアプリでそれを行う正しい方法です。
その理由は、WebアプリをWARにパッケージ化すると、ファイルシステムからの読み取りが機能しないためです。これは、Webアプリをパッケージ化するための適切な方法です。絶対ファイルパスやアプリサーバーがインストールされている場所に依存しないため、この方法で移植できます。
FileInputStream は、コンストラクターに渡すファイル パスを、Java プロセスの作業ディレクトリからの相対パスとして読み込みます。通常、Web コンテナーでは、これはbin
フォルダーのようなものです。
getResourceAsStream()
アプリケーションの classpath から相対的なファイル パスをロードします。
このFileInputStream
クラスは、基になるファイル システムと直接連携します。問題のファイルがそこに物理的に存在しない場合、開くことができません。getResourceAsStream()
メソッドの動作は異なります。ClassLoader
呼び出されたクラスのを使用して、リソースを見つけてロードしようとします。これにより、たとえば、jar
ファイルに埋め込まれたリソースを見つけることができます。
classname.getResourceAsStream() は、classname のクラスローダーを介してファイルをロードします。クラスが jar ファイルから取得された場合、そこからリソースがロードされます。
FileInputStream は、ファイルシステムからファイルを読み取るために使用されます。