web-dev-qa-db-ja.com

getClass()。getResource()によるファイルの読み込み

getClass.getResource(path)を使用してリソースファイルをロードする方法に従いました。コードのスニペットは次のとおりです。

String url = "Test.properties";

System.out.println("Before printing paths..");
System.out.println("Path2: "+ getClass().getResource(url).getPath());

FileInputStream inputStream = new FileInputStream(new File(getClass().getResource(url).toURI()));
i_propConfig.load(inputStream);
inputStream.close();

Eclipseで階層を設定しました(ソースの下にはSwingDemoというフォルダーがあります。SwingDemoには、Javaファイルとリソースファイルがあります)...

  1. src
    • SwingDemo
      1. CustomDialog.Java
      2. Test.properties

Eclipseでこれを実行すると、すべてが正常に実行されます。しかし、cmd行からアプリを実行しようとするとすぐに、nullポインター例外が発生します。

コマンドラインの展開階層は次のとおりです。

フォルダー:D:\Work\Java Progrms\SwingDemo

階層:

  1. SwingDemo
    • CustomDialog.Java
    • Test.properties

まず、このファイルをコマンドライン(javac CustomDialog.Java)からSwingDemoフォルダー内にコンパイルしました。次に、Java Programsフォルダーに戻り(.Javaクラス内のパッケージについて述べたように)、有名な

Java SwingDemo.CustomDialog

以前に新しいFileInputStream( "path")を使用したときは、同様の手順に従いました。この方法を実行した後、nullポインター例外が発生しています。

getClass().getResource(url)は特定のディレクトリからファイルをロードできないと思います。そのため、リソースをJavaファイルと同じディレクトリに配置します。 Eclipseで問題なく動作しました。しかし、なぜコマンドラインから実行すると、これがエラーになりますか。

42
AnjanN

getClass().getResource()は、クラスローダーを使用してリソースをロードします。これは、リソースがロードされるクラスパスにある必要があることを意味します。

Eclipseで実行する場合、ソースフォルダーに入れたものはすべてEclipseによって「コンパイル」されます。

  • .Javaファイルは、binディレクトリに移動する.classファイルにコンパイルされます(デフォルト)
  • 他のファイルはbinディレクトリにコピーされます(パッケージ/フォルダーhirearchyを考慮)

Eclipseでプログラムを起動すると、binディレクトリはクラスパスにあり、Test.propertiesファイルが含まれているため、このファイルはgetResource()またはgetResourceAsStream()を使用してクラスローダーによってロードできます。

コマンドラインから機能しない場合は、ファイルがクラスパスにないためです。

すべきではないことに注意してください

FileInputStream inputStream = new FileInputStream(new File(getClass().getResource(url).toURI()));

リソースをロードします。ファイルがファイルシステムからロードされている場合にのみ機能するためです。アプリをjarファイルにパッケージ化する場合、またはネットワーク経由でクラスをロードする場合、機能しません。 InputStreamを取得するには、単に使用します

getClass().getResourceAsStream("Test.properties")

そして最後に、ドキュメントが示すように、

Foo.class.getResourceAsStream("Test.properties")

クラスFooと同じパッケージにあるTest.propertiesファイルをロードします。

Foo.class.getResourceAsStream("/com/foo/bar/Test.properties")

パッケージcom.foo.barにあるTest.propertiesファイルをロードします。

72
JB Nizet

Jar内のリソースフォルダーからファイルにアクセスする最良の方法は、getResourceAsStreamを介してInputStreamを使用することです。リソースをファイルインスタンスとして引き続き必要とする場合は、リソースをストリームとして一時ファイルにコピーできます(一時ファイルはJVMの終了時に削除されます)。

public static File getResourceAsFile(String resourcePath) {
    try {
        InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(resourcePath);
        if (in == null) {
            return null;
        }

        File tempFile = File.createTempFile(String.valueOf(in.hashCode()), ".tmp");
        tempFile.deleteOnExit();

        try (FileOutputStream out = new FileOutputStream(tempFile)) {
            //copy stream
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        }
        return tempFile;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}
16
Lukas Masuch