176

Class.getResource(String)クラスパス リソース (たとえば、から取得するもの) を として取得する API はありますjava.nio.file.Pathか? Path理想的には、クラスパス リソースを備えた派手な新しい APIを使用したいと考えています。

4

8 に答える 8

225

これは私のために働きます:

return Paths.get(ClassLoader.getSystemResource(resourceName).toURI());
于 2014-05-14T11:59:15.290 に答える
29

あなたがやりたいことは、Files.lines(...)おそらくjar内から、クラスパスからのリソースを呼び出すことだと思います。

Oracle は、jar ファイルに存在する場合に使用可能なパスを返さないようにすることで、aPathが aである場合の概念を複雑にしたため、次のようなことを行う必要があります。PathgetResource

Stream<String> stream = new BufferedReader(new InputStreamReader(ClassLoader.getSystemResourceAsStream("/filename.txt"))).lines();
于 2015-09-15T06:57:37.693 に答える
13

最も一般的な解決策は次のとおりです。

interface IOConsumer<T> {
    void accept(T t) throws IOException;
}
public static void processRessource(URI uri, IOConsumer<Path> action) throws IOException{
    try {
        Path p=Paths.get(uri);
        action.accept(p);
    }
    catch(FileSystemNotFoundException ex) {
        try(FileSystem fs = FileSystems.newFileSystem(
                uri, Collections.<String,Object>emptyMap())) {
            Path p = fs.provider().getPath(uri);
            action.accept(p);
        }
    }
}

主な障害は、2 つの可能性に対処することです。使用する必要があるが閉じない既存のファイルシステム ( fileURI や Java 9 のモジュールストレージなど) と、ファイルシステムを自分で開いて安全に閉じなければならない ( zip/jar ファイル)。

したがって、上記のソリューションは、実際のアクションを にカプセル化し、interface両方のケースを処理し、2 番目のケースでは後で安全に閉じ、Java 7 から Java 18 まで機能します。アプリケーションの別のコンポーネントが同じ zip/jar ファイルのファイルシステムをすでに開いている場合にも機能します。

これは、上記のすべての Java バージョンで使用できます。たとえば、次のように、パッケージ (java.lang例では)の内容をPathsとして一覧表示するために使用できます。

processRessource(Object.class.getResource("Object.class").toURI(),new IOConsumer<Path>(){
    public void accept(Path path) throws IOException {
        try(DirectoryStream<Path> ds = Files.newDirectoryStream(path.getParent())) {
            for(Path p: ds)
                System.out.println(p);
        }
    }
});

Java 8 以降では、ラムダ式またはメソッド参照を使用して実際のアクションを表すことができます。

processRessource(Object.class.getResource("Object.class").toURI(), path -> {
    try(Stream<Path> stream = Files.list(path.getParent())) {
        stream.forEach(System.out::println);
    }
});

同じことをする。


Java 9 のモジュール システムの最終リリースでは、上記のコード例が壊れています。9 から 12 までの Java バージョンでは、本来あるべき のパス/java.base/java/lang/Object.classが一貫して返さPaths.get(Object.class.getResource("Object.class"))れません/modules/java.base/java/lang/Object.class/modules/これは、親パスが存在しないと報告されたときに欠落しているパスを先頭に追加することで修正できます。

processRessource(Object.class.getResource("Object.class").toURI(), path -> {
    Path p = path.getParent();
    if(!Files.exists(p))
        p = p.resolve("/modules").resolve(p.getRoot().relativize(p));
    try(Stream<Path> stream = Files.list(p)) {
        stream.forEach(System.out::println);
    }
});

その後、すべてのバージョンと保存方法で再び機能します。JDK 13 以降、この回避策は不要になりました。

于 2016-03-15T20:10:47.947 に答える
1

jar ファイル内のリソースから URI を作成することはできません。単に一時ファイルに書き込んでから使用できます(java8):

Path path = File.createTempFile("some", "address").toPath();
Files.copy(ClassLoader.getSystemResourceAsStream("/path/to/resource"), path, StandardCopyOption.REPLACE_EXISTING);
于 2016-10-05T18:54:20.763 に答える
0

https://docs.oracle.com/javase/8/docs/technotes/guides/io/fsp/zipfilesystemprovider.htmlに記載されているように、jarファイルからリソースを読み取るようにファイルシステムを定義する必要があります。以下のコードでjarファイルからリソースを読み取ることに成功しました:

Map<String, Object> env = new HashMap<>();
try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {

        Path path = fs.getPath("/path/myResource");

        try (Stream<String> lines = Files.lines(path)) {
            ....
        }
    }
于 2015-12-02T10:26:28.090 に答える