181

webapp でファイルをロードしようとしていて、FileNotFound使用すると例外が発生しましたFileInputStream。ただし、同じパスを使用して、ファイルを読み込んだときにファイルを読み込むことができましたgetResourceAsStream()。2 つの方法の違いは何ですか? また、一方が機能し、他方が機能しないのはなぜですか?

4

6 に答える 6

260

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 では、相対パスではなく絶対パスを使用することをお勧めします。FileC:\full\path\to\file.ext

Java (Web) アプリケーションで絶対パスをハードコードしたり、推測したりしたくありません。これは単なる移植性の問題です (つまり、システム X では動作しますが、システム Y では動作しません)。通常の方法では、これらの種類のリソースをclasspathに配置するか、そのフル パスをクラスパスに追加します (Eclipse などの IDE では、srcそれぞれフォルダーと「ビルド パス」になります)。このようにして、ClassLoaderby ClassLoader#getResource()またはを使用してそれらを取得できますClassLoader#getResourceAsStream()。偶然にもわかったように、クラスパスの「ルート」に関連するファイルを見つけることができます。Web アプリケーション (または複数のクラスローダーを使用するその他のアプリケーション) では、このためClassLoaderに返される asを使用することをお勧めします。これにより、Web アプリケーションThread.currentThread().getContextClassLoader()コンテキストの「外側」も確認できます。

webapps のもう 1 つの代替手段は、ServletContext#getResource()とそれに対応するServletContext#getResourceAsStream()です。webフォルダーを含む、webapp プロジェクトの public フォルダーにあるファイルにアクセスでき/WEB-INFます。はServletContext継承されたgetServletContext()メソッドによってサーブレットで使用でき、そのまま呼び出すことができます。

以下も参照してください。

于 2010-02-22T01:59:29.290 に答える
28

getResourceAsStream(すでに学んだように)Webアプリでそれを行う正しい方法です。

その理由は、WebアプリをWARにパッケージ化すると、ファイルシステムからの読み取りが機能しないためです。これは、Webアプリをパッケージ化するための適切な方法です。絶対ファイルパスやアプリサーバーがインストールされている場所に依存しないため、この方法で移植できます。

于 2010-02-22T01:03:13.320 に答える
15

FileInputStream は、コンストラクターに渡すファイル パスを、Java プロセスの作業ディレクトリからの相対パスとして読み込みます。通常、Web コンテナーでは、これはbinフォルダーのようなものです。

getResourceAsStream()アプリケーションの classpath から相対的なファイル パスをロードします。

于 2010-02-22T00:57:14.890 に答える
13

このFileInputStreamクラスは、基になるファイル システムと直接連携します。問題のファイルがそこに物理的に存在しない場合、開くことができません。getResourceAsStream()メソッドの動作は異なります。ClassLoader呼び出されたクラスのを使用して、リソースを見つけてロードしようとします。これにより、たとえば、jarファイルに埋め込まれたリソースを見つけることができます。

于 2010-02-22T00:57:59.437 に答える
8

classname.getResourceAsStream() は、classname のクラスローダーを介してファイルをロードします。クラスが jar ファイルから取得された場合、そこからリソースがロードされます。

FileInputStream は、ファイルシステムからファイルを読み取るために使用されます。

于 2010-02-22T00:59:47.500 に答える