Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I get ProviderMismatchException when I try to .relativize() a Path against another Path?

[note: self answered question]

I have opened a FileSystem to a zip file using java.nio. I have gotten a Path from that filesystem:

final Path zipPath = zipfs.getPath("path/into/zip");

Now I have a directory on the local filesystem which I have obtained using:

final Path localDir = Paths.get("/local/dir")

I want to test whether /local/dir/path/into/zip exists, so I check its existence using:

Files.exists(localDir.resolve(zipPath))

but I get a ProviderMismatchException. Why? How do I fix this?

like image 633
fge Avatar asked Mar 24 '14 14:03

fge


People also ask

What does @path do in Java?

A Path can represent a root, a root and a sequence of names, or simply one or more name elements. A Path is considered to be an empty path if it consists solely of one name element that is empty. Accessing a file using an empty path is equivalent to accessing the default directory of the file system.

What is path object in Java?

A Path object contains the file name and directory list used to construct the path and is used to examine, locate, and manipulate files. The helper class, java. nio. file. Paths (in plural form) is the formal way of creating Path objects.

What is resolve in Java?

resolve(String other) method of java. nio. file. Path used to converts a given path string to a Path and resolves it against this Path in the exact same manner as specified by the resolve method.


1 Answers

This behaviour is documented, albeit it is not very visible. You have to delve into the java.nio.file package description to see, right at the end, that:

Unless otherwise noted, invoking a method of any class or interface in this package created by one provider with a parameter that is an object created by another provider, will throw ProviderMismatchException.

The reasons for this behaviour may not be obvious, but consider for instance that two filesystems can define a different separator.

There is no method in the JDK which will help you there. If your filesystems use the same separator then you can work around this using:

path1.resolve(path2.toString())

Otherwise this utility method can help:

public static Path pathTransform(final FileSystem fs, final Path path)
{
    Path ret = fs.getPath(path.isAbsolute() ? fs.getSeparator() : "");
    for (final Path component: path)
        ret = ret.resolve(component.getFileName().toString());
    return ret;
}

Then the above can be written as:

final Path localPath = pathTransform(localDir.getFileSystem(), zipPath);
Files.exists(localDir.resolve(localPath));
like image 61
fge Avatar answered Oct 20 '22 00:10

fge