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
フォルダーと「ビルドパス」です)。このようにして、ClassLoader
by 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などのパッケージ化されたファイルからファイルをロードする場合に最適です。