Javaで相対パスを使用してリソースを開く


84

私のJavaアプリでは、いくつかのファイルとディレクトリを取得する必要があります。

これはプログラム構造です:

./main.java
./package1/guiclass.java
./package1/resources/resourcesloader.java
./package1/resources/repository/modules/   -> this is the dir I need to get
./package1/resources/repository/SSL-Key/cert.jks    -> this is the file I need to get

guiclass リソース(ディレクトリとファイル)をロードするresourcesloaderクラスをロードします。

ファイルに関しては、私は試しました

resourcesloader.class.getClass().getResource("repository/SSL-Key/cert.jks").toString()

実際のパスを取得するためですが、この方法は機能しません。

ディレクトリの作り方がわかりません。


1
class.getClass()はclass.getClassLoader()と同じではありません。別の解決策もあります。リソースと同じパッケージ内のクラスを使用するgetResourceAsStream()です。詳細については、tshikatshikaaa.blogspot.nl / 2012/07 / …をご覧ください。
ジェローム・Verstrynge

回答:


48

ローダーを取得するクラスではなく、クラスローダーに関連するパスを指定します。例えば:

resourcesloader.class.getClassLoader().getResource("package1/resources/repository/SSL-Key/cert.jks").toString();

160

このgetClass().getResource("filename.txt")方法の使用に問題がありました。Java docsの説明を読んだときに、リソースがリソースにアクセスしようとしているクラスと同じパッケージにない場合は、で始まる相対パスを指定する必要があります'/'。推奨される戦略は、リソースファイルをルートディレクトリの「resources」フォルダに配置することです。したがって、たとえば、構造がある場合:

src/main/com/mycompany/myapp

次に、mavenが推奨するリソースフォルダーを次の場所に追加できます。

src/main/resources

さらに、resourcesフォルダーにサブフォルダーを追加できます

src/main/resources/textfiles

ファイルが呼び出されたmyfile.txtので、

src/main/resources/textfiles/myfile.txt

ここで、愚かなパスの問題が発生します。にクラスがあり、リソースフォルダからファイルcom.mycompany.myapp packageにアクセスするとしmyfile.txtます。あなたが与える必要があると言う人もいます:

"/main/resources/textfiles/myfile.txt" path

または

"/resources/textfiles/myfile.txt"

これらは両方とも間違っています。実行後mvn clean compile、ファイルとフォルダーは次の場所にコピーされます。

myapp/target/classes 

フォルダ。ただし、resourcesフォルダーはありません。resourcesフォルダー内のフォルダーのみです。だからあなたは持っています:

myapp/target/classes/textfiles/myfile.txt

myapp/target/classes/com/mycompany/myapp/*

したがって、getClass().getResource("")メソッドに与える正しいパスは次のとおりです。

"/textfiles/myfile.txt"

ここにあります:

getClass().getResource("/textfiles/myfile.txt")

これでnullは返されなくなりますが、クラスは返されます。これが誰かに役立つことを願っています。"resources"フォルダーもコピーされず、フォルダー内のサブフォルダーとファイルのみが直接コピーされるのは不思議です"resources""resources"フォルダが下にもあることは私には論理的に思えます"myapp/target/classes"


1
私のtarget/classes場合、メインリソースの下にあるファイルのみが表示され、テストリソースは表示されません。どうして?
Ava 2015

@Avaソースフォルダーとしてテストフォルダーを追加すれば、準備完了です。
Aakash Parashar 2016年

@Ava、確かにあなたにとっては遅い答えですが、誰かを助けるかもしれません。mvn clean test-compileコマンドは、Mavenライフサイクルのcompileで実行されるため、実行する必要があります。が生成されtarget/test-classesます。
アレクサンダーラチェンコ

34

これを他の人ほど早く理解しない人のために追加情報を提供することを期待して、セットアップが少し異なるので私のシナリオを提供したいと思います。私のプロジェクトは、次のディレクトリ構造でセットアップされました(Eclipseを使用)。

事業/
  src ///アプリケーションのソースコード
    org /
      私のプロジェクト/
        MyClass.java
  test ///ユニットテスト
  res ///リソース
    images ///アイコンのPNG画像
      my-image.png
    xml / // JAXBでXMLファイルを検証するためのXSDファイル
      my-schema.xsd
    conf / // Log4jのデフォルトの.confファイル
      log4j.conf
  lib ///プロジェクト設定を介してビルドパスに追加されたライブラリ

resディレクトリからリソースをロードする際に問題が発生しました。すべてのリソースをソースコードとは別にしたかった(単に管理/編成の目的で)。だから、私は何をしていたことを追加した解像度のにディレクトリをビルドパスし、その後経由でリソースにアクセスします。

static final ClassLoader loader = MyClass.class.getClassLoader();

// in some function
loader.getResource("images/my-image.png");
loader.getResource("xml/my-schema.xsd");
loader.getResource("conf/log4j.conf");

注:/私は使用していますので、リソース文字列の先頭から省略されて ClassLoader.getResource(String)を代わりにClass.getResource(String)を


1
ClassLoaderを提案するための。+ 1
pyb 2014年

1
このテーマに関するベストアンサー!/リソースパスの先頭で使用しないことに関するヒントが重要でした。
カイハドリン2016

10

クラスで「getResource」を使用すると、相対パスはクラスが含まれているパッケージに基づいて解決されます。ClassLoaderで「getResource」を使用すると、相対パスはルートフォルダーに基づいて解決されます。

絶対パスを使用する場合、両方の「getResource」メソッドはルートフォルダーから開始されます。


の影響を忘れないでください/
Gilberto

@nbeyergetResource絶対パスでの使用がルートフォルダから始まるのはなぜですか?絶対パスの目的ではありません絶対
atjua 2017年

10

@GianCarlo:Javaプロジェクトのルートを取得するシステムプロパティuser.dirを呼び出してから、このパスを相対パスに追加してみてください。例:

String root = System.getProperty("user.dir");
String filepath = "/path/to/yourfile.txt"; // in case of Windows: "\\path \\to\\yourfile.txt
String abspath = root+filepath;



// using above path read your file into byte []
File file = new File(abspath);
FileInputStream fis = new FileInputStream(file);
byte []filebytes = new byte[(int)file.length()];
fis.read(filebytes);

1
OPは、クラスパス内(おそらくビルド中に生成されたjar内)にリソースを配置したいと考えていました。この方法では、その目標を達成する方法は提供されませんFile。jarファイル内のリソースを指すことはできず、ファイルシステム内の適切なエントリ(jar自体など)のみを指すことができます。
アッティラ

「user.dir」を取得して目的のパスを表示するというアイデアが好きです。おかげで
YouAreAwesome

5

Eclipse + Mavenを使用している場合。のファイルimages/pic.jpgにアクセスしようとしたとしますsrc/main/resources。このようにする:

ClassLoader loader = MyClass.class.getClassLoader();
File file = new File(loader.getResource("images/pic.jpg").getFile());

は完全に正しいですが、nullポインタ例外が発生する可能性があります。Eclipseは、Mavenディレクトリ構造内のフォルダーをソースフォルダーとしてすぐに認識しないようです。src/main/resourcesプロジェクトのソースフォルダーリストからフォルダーを削除して元に戻す(プロジェクト>プロパティ> Javaビルドパス>ソース>フォルダーの削除/追加)ことで、これを解決することができました。


2
resourcesloader.class.getClass()

次のように分類できます。

Class<resourcesloader> clazz = resourceloader.class;
Class<Class> classClass = clazz.getClass();

これは、ブートストラップクラスを使用してリソースをロードしようとしていることを意味します。

代わりに、おそらく次のようなものが必要です。

resourcesloader.class.getResource("repository/SSL-Key/cert.jks").toString()

javacだけが非静的コンテキストで静的メソッドを呼び出すことについて警告した場合...


1

次の作業をしますか?

resourcesloader.class.getClass().getResource("/package1/resources/repository/SSL-Key/cert.jks")

パッケージを含むフルパスを指定できない理由はありますか?


1

上記の2つの答えを使用します。最初の1つ

resourcesloader.class.getClassLoader().getResource("package1/resources/repository/SSL-Key/cert.jks").toString();
resourcesloader.class.getResource("repository/SSL-Key/cert.jks").toString()

一つの同じものでなければなりませんか?


1

ファイルへの実際のパスを取得するには、次のことを試してください。

URL fileUrl = Resourceloader.class.getResource("resources/repository/SSL-Key/cert.jks");
String pathToClass = fileUrl.getPath;    

ここでは、Resourceloaderはクラス名です。「resources / repository / SSL-Key / cert.jks」は、ファイルへの相対パスです。./package1/javaにguiclassがあり、残りのフォルダー構造が残っている場合、相対パスを定義するルールがあるため、相対パスとして「../resources/repository/SSL-Key/cert.jks」を使用します。

このようにして、BufferedReaderでファイルを読み取ることができます。ファイルへのパスを識別するために文字列を使用しないでください。パスにスペースまたは英語以外のアルファベットの文字が含まれていると、問題が発生し、ファイルが見つかりません。

BufferedReader bufferedReader = new BufferedReader(
                        new InputStreamReader(fileUrl.openStream()));

0

.getFile()ヌルポインタ例外を回避し、データディレクトリへのパスを設定するために、@ jonathan.coneの1つのライナーに(を追加して)小さな変更を加えました。これが私のために働いたものです:

String realmID = new java.util.Scanner(new java.io.File(RandomDataGenerator.class.getClassLoader().getResource("data/aa-qa-id.csv").getFile().toString())).next();

0

これを使って:

resourcesloader.class.getClassLoader().getResource("/path/to/file").**getPath();**
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.