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