1. 概要

このチュートリアルでは、Javaアプリケーションでリソースファイルを読み取るときに発生する可能性のある問題について説明します。実行時に、リソースフォルダーがディスク上のソースコードと同じ場所にあることはめったにありません。

コードがパッケージ化された後、Javaでリソースファイルにアクセスする方法を見てみましょう。

2. ファイルの読み取り

アプリケーションが起動時にファイルを読み取るとしましょう。

try (FileReader fileReader = new FileReader("src/main/resources/input.txt"); 
     BufferedReader reader = new BufferedReader(fileReader)) {
    String contents = reader.lines()
      .collect(Collectors.joining(System.lineSeparator()));
}

上記のコードをIDEで実行すると、ファイルはエラーなしでロードされます。 これは、 IDEがプロジェクトディレクトリを現在の作業ディレクトリとして使用し、 src / main /resourcesディレクトリがアプリケーションが読み取るためにそこにあるためです。

ここで、 MavenJARプラグインを使用してコードをJARとしてパッケージ化するとします。

コマンドラインで実行すると、次のようになります。

java -jar core-java-io2.jar

次のエラーが表示されます。

Exception in thread "main" java.io.FileNotFoundException: 
    src/main/resources/input.txt (No such file or directory)
	at java.io.FileInputStream.open0(Native Method)
	at java.io.FileInputStream.open(FileInputStream.java:195)
	at java.io.FileInputStream.<init>(FileInputStream.java:138)
	at java.io.FileInputStream.<init>(FileInputStream.java:93)
	at java.io.FileReader.<init>(FileReader.java:58)
	at com.baeldung.resource.MyResourceLoader.loadResourceWithReader(MyResourceLoader.java:14)
	at com.baeldung.resource.MyResourceLoader.main(MyResourceLoader.java:37)

3. ソースコードとコンパイルされたコード

JARを構築すると、リソースはパッケージ化されたアーティファクトのルートディレクトリに配置されます。

この例では、ソースコードのセットアップで、ソースコードディレクトリの src / main /resourcesinput.txtが含まれていることがわかります。

ただし、対応するJAR構造では、次のように表示されます。

META-INF/MANIFEST.MF
META-INF/
com/
com/baeldung/
com/baeldung/resource/
META-INF/maven/
META-INF/maven/com.baeldung/
META-INF/maven/com.baeldung/core-java-io-files/
input.txt
com/baeldung/resource/MyResourceLoader.class
META-INF/maven/com.baeldung/core-java-io-files/pom.xml
META-INF/maven/com.baeldung/core-java-io-files/pom.properties

ここで、input.txtはJARのルートディレクトリにあります。 したがって、コードを実行すると、FileNotFoundExceptionが表示されます。

パスをに変更しても /input.txt 元のコードはこのファイルを次のようにロードできませんでしたリソースは通常、ディスク上のファイルとしてアドレス指定できません。 リソースファイルはJAR内にパッケージ化されているため、それらにアクセスする別の方法が必要です。

4. 資力

代わりに、リソースの読み込みを使用して、特定のファイルの場所ではなく、クラスパスからリソースを読み込みます。 これは、コードがどのようにパッケージ化されているかに関係なく機能します。

try (InputStream inputStream = getClass().getResourceAsStream("/input.txt");
    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
    String contents = reader.lines()
      .collect(Collectors.joining(System.lineSeparator()));
}

ClassLoader.getResourceAsStream()は、指定されたリソースのクラスパスを調べます。 getResourceAsStream()への入力の先頭のスラッシュは、クラスパスのベースから読み取るようにローダーに指示します。 JARファイルの内容はクラスパスにあるため、このメソッドは機能します。

IDEは通常、クラスパスにsrc / main / resourcesを含め、ファイルを検索します。

5. 結論

この簡単な記事では、クラスパスリソースとしてファイルの読み込みを実装し、パッケージ化された方法に関係なくコードが一貫して機能できるようにしました。

いつものように、サンプルコードはGitHubから入手できます。