java.nio.file.Path for a classpath resource

后端 未结 8 997
自闭症患者
自闭症患者 2020-11-28 02:55

Is there an API to get a classpath resource (e.g. what I\'d get from Class.getResource(String)) as a java.nio.file.Path? Ideally, I\'d like to use the fancy new Path<

8条回答
  •  忘掉有多难
    2020-11-28 03:41

    It turns out you can do this, with the help of the built-in Zip File System provider. However, passing a resource URI directly to Paths.get won't work; instead, one must first create a zip filesystem for the jar URI without the entry name, then refer to the entry in that filesystem:

    static Path resourceToPath(URL resource)
    throws IOException,
           URISyntaxException {
    
        Objects.requireNonNull(resource, "Resource URL cannot be null");
        URI uri = resource.toURI();
    
        String scheme = uri.getScheme();
        if (scheme.equals("file")) {
            return Paths.get(uri);
        }
    
        if (!scheme.equals("jar")) {
            throw new IllegalArgumentException("Cannot convert to Path: " + uri);
        }
    
        String s = uri.toString();
        int separator = s.indexOf("!/");
        String entryName = s.substring(separator + 2);
        URI fileURI = URI.create(s.substring(0, separator));
    
        FileSystem fs = FileSystems.newFileSystem(fileURI,
            Collections.emptyMap());
        return fs.getPath(entryName);
    }
    

    Update:

    It’s been rightly pointed out that the above code contains a resource leak, since the code opens a new FileSystem object but never closes it. The best approach is to pass a Consumer-like worker object, much like how Holger’s answer does it. Open the ZipFS FileSystem just long enough for the worker to do whatever it needs to do with the Path (as long as the worker doesn’t try to store the Path object for later use), then close the FileSystem.

提交回复
热议问题