WebアプリケーションにファイルをロードしようとしていましたがFileNotFound、を使用すると例外が発生しましたFileInputStream。しかし、同じパスを使用して、ファイルを読み込むことができましたgetResourceAsStream()。2つの方法の違いは何ですか?なぜ一方が機能し、もう一方が機能しないのですか?
WebアプリケーションにファイルをロードしようとしていましたがFileNotFound、を使用すると例外が発生しましたFileInputStream。しかし、同じパスを使用して、ファイルを読み込むことができましたgetResourceAsStream()。2つの方法の違いは何ですか?なぜ一方が機能し、もう一方が機能しないのですか?
回答:
java.io.FileそしてCONSORTSは、ローカルディスクのファイルシステムに作用します。問題の根本的な原因は、の相対パスjava.ioが現在の作業ディレクトリに依存していることです。つまり、JVM(あなたの場合:ウェブサーバーの)が起動されるディレクトリです。これは、たとえば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フォルダーと「ビルドパス」です)。このようにして、ClassLoaderby ClassLoader#getResource()またはの助けを借りてそれらをつかむことができますClassLoader#getResourceAsStream()。偶然にわかったように、クラスパスの「ルート」に関連するファイルを見つけることができます。Webアプリケーション(または複数のクラスローダーを使用するその他のアプリケーション)では、このためClassLoaderにによって返されるを使用することをお勧めします。Thread.currentThread().getContextClassLoader()これにより、Webアプリケーションコンテキストの「外側」も確認できます。
webappsのもう1つの代替方法は、ServletContext#getResource()およびその対応物ServletContext#getResourceAsStream()です。webフォルダーを含む、webappプロジェクトのパブリックフォルダーにあるファイルにアクセスでき/WEB-INFます。ServletContext継承されたことにより、サーブレットで利用可能でgetServletContext()、あるとして、あなたがそれを呼び出すことができる、方法。
getResourceAsStream (すでに学んだように)ウェブアプリでそれを行う正しい方法です。
その理由は、WebアプリをWARにパッケージ化すると、ファイルシステムからの読み取りが機能しないためです。これは、Webアプリをパッケージ化する適切な方法です。絶対ファイルパスやアプリサーバーがインストールされている場所に依存しないため、この方法で移植できます。
FileInputStreamは、Javaプロセスの作業ディレクトリからの相対パスとして、コンストラクタに渡すファイルパスをロードします。通常、Webコンテナーでは、これはbinフォルダーのようなものです。
getResourceAsStream()アプリケーションのクラスパスからの相対ファイルパスをロードします。
このFileInputStreamクラスは、基になるファイルシステムと直接連携します。問題のファイルがそこに物理的に存在しない場合、ファイルを開くことができません。getResourceAsStream()この方法は、動作が異なります。ClassLoader呼び出されたクラスのを使用して、リソースを見つけてロードしようとします。これにより、たとえば、jarファイルに埋め込まれたリソースを見つけることができます。
jarファイル形式とその影響について知らない限り、これらは通常、ファイルシステム内の独立したエンティティとは見なされません。そしてJavaでは、適切な人ClassLoaderがこの知識を持っているかもしれませんが、プレーンはFileInputStream確かに持っていません。
ここでは、File Read(java.io)とResource Read(ClassLoader.getResourceAsStream())としてマークして両方の使用法を分離しています。
ファイルの読み取り-1 .ローカルファイルシステムで動作します。2.現在のJVM起動ディレクトリから要求されたファイルをrootとして見つけようとします。
リソースの読み取り -1.クラスパスで動作します。2.現在または親のクラスローダークラスパスでファイル/リソースを見つけようとします。3. warやjarなどのパッケージ化されたファイルからファイルをロードする場合に最適です。