ファイルとしてのJavaリソース


122

Javaでクラスローダーを介してjarから取得したリソースにFileインスタンスを構築する方法はありますか?

私のアプリケーションは、jar(デフォルト)または実行時に指定されたファイルシステムディレクトリ(ユーザー入力)のいくつかのファイルを使用します。私は一貫した方法を探し
ています
a)これらのファイルをストリームとしてロードするb)ユーザー定義のディレクトリまたはjarのディレクトリにあるファイルをそれぞれリストする

編集:どうやら、理想的なアプローチは、java.io.Fileから完全に離れることです。クラスパスからディレクトリをロードし、その内容(そこに含まれるファイル/エンティティ)を一覧表示する方法はありますか?

回答:


58

ClassLoader.getResourceAsStreamそしてClass.getResourceAsStream間違いなくリソースデータをロードするために行く方法です。ただし、クラスパスの要素のコンテンツを「一覧表示」する方法はないと思います。

場合によっては、これは単に不可能であるClassLoader 可能性があります。たとえば、要求されたリソース名に基づいて、オンザフライでデータを生成できます。あなたが見ればClassLoader(クラスパスメカニズムを通じどのような作品は基本的である)APIあなたが欲しいものを行うには何がありません表示されます。

実際にjarファイルを取得していることがわかっている場合は、それをロードしてZipInputStream、何が利用可能かを調べることができます。ただし、ディレクトリとjarファイルのコードが異なることになります。

最初にファイルを個別に作成する場合の1つの代替方法は、使用可能なリソースのリストを含む一種のマニフェストファイルを含めることです。それをjarファイルにバンドルするか、ファイルシステムにファイルとして含め、ユーザーにリソースの選択肢を提供する前にロードします。


3
私はそれが煩わしいことに同意します-しかし、それはClassLoaderを他の方法でより広く適用できるようにします。たとえば、ウェブはファイルのフェッチに適しているため、「ウェブクラスローダー」を書くのは簡単ですが、通常はファイルをリストしません。
Jon Skeet、

ロードしようとしているリソースが1MiBよりもはるかに大きい場合InputStreamgetResourceAsStreamストップから取得して、そのサイズの後にリソースのバイトを取得し、jarなどの圧縮ファイルシステムに含まれている場合は0を返します。getResourceその場合、これとは別にファイルを使用してロードする必要があります。
mgttlinger 2015

1
@mgttlinger:それは私にはありそうにないように思えます...もし可能であれば、再現で新しい質問を投稿する価値があります。
Jon Skeet、2015

この問題はread、読み取るデータの量を決定するメソッドが原因でした(私はそれを知りませんでした)。そして、読み込まれているファイルが通常のフォルダにある場合、ファイル全体が読み込まれるようです。パッケージ化されているためにファイルがjar内にある場合、その一部のみを読み取ります。
mgttlinger

1
@mgttlinger:いいえ、それはその一部を読み取るだけではありません-しかし、それはすべての読み取り呼び出しで提供されるバッファー全体を埋めることはできません。いつものようにInputStream、リソース全体を読み取りたい場合readは、-1が返されるまでループする必要があります。
Jon Skeet、2015

98

私は同じ問題を抱えていて、以下を使用することができました:

// Load the directory as a resource
URL dir_url = ClassLoader.getSystemResource(dir_path);
// Turn the resource into a File object
File dir = new File(dir_url.toURI());
// List the directory
String files = dir.list()

45
このアプローチは、クラスパスのJARでは機能せず、ファイルとディレクトリでのみ機能します
yegor256

1
@ yegor256ファイルがjarにある場合、FileSystemオブジェクトを作成してPathそこからを取得できます。その後、通常どおりに読み取ることができます。(stackoverflow.com/a/22605905/1876344を参照)
mgttlinger

53

これが私のアプリケーションの1つからのコードの一部です...それがあなたのニーズに合っているかどうか私に知らせてください。使用するファイルがわかっている場合は、これを使用できます。

URL defaultImage = ClassA.class.getResource("/packageA/subPackage/image-name.png");
File imageFile = new File(defaultImage.toURI());

お役に立てば幸いです。


はい、ありtoURI()ませんが、失敗します。
Olivier Faucheux

10

jarから取得したリソースでFileインスタンスを構築する信頼できる方法は、リソースをストリームとして一時ファイルにコピーすることです(一時ファイルは、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;
    }
}

4

これを試して:

ClassLoader.getResourceAsStream ("some/pkg/resource.properties");

利用可能なメソッドは他にもあります。たとえば、http//www.javaworld.com/javaworld/javaqa/2003-08/01-qa-0808-property.htmlを参照して ください。


御返答いただき有難うございます。getResourceAsStreamについては知っていますが、それを介してクラスパスからディレクトリをロードできないと思います。
Mantrum 2009年

Javaのディレクトリはファイル(UNIXのルーツだと思います)なので、少なくとも試す必要があります。
topchef 2009年

java.io.Fileを使用する必要があるディレクトリにファイルをリストすると思います。Fileに渡すことができるURLを返すClassLoader.findResourceでファイルを検索できます。
Nathan Voxland 2009年

2

これは1つのオプションです。http//www.uofr.net/~greg/java/get-resource-listing.html


4
このリンクは質問に答えるかもしれないが、好ましいと考えられるリンクは、それによって答えは無用作り、変更される可能性がありまたはリンクされたページを除去することができるよう、ここでは答えの重要な部分が含まれ、参照のためのリンクを提供します。
JonasCz-モニカの復活2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.