Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java.nio.file.Path.contains(subPath)?

Tags:

java

nio

I need to check whether a given path is a subpath anywhere within another path and was wondering whether there exists such a method already before writing my own.

Here is some code that may help to understand the problem:

Path someRealPath = Paths.get("/tmp/some/path/to/somewhere");
Path subpathToCheck = Paths.get("some/path");

// I am expecting something similar as follows:
someRealPath.contains(subPathToCheck) // should return true in this case
someRealPath.contains(Paths.get("some/to")) // should return false

I already saw relativize, but I don't think that's the easiest way to solve the problem. The simplest I came up with was normalize().toString().contains(/* other normalized string path */). But maybe there is an easier way? Lots of methods inside Paths look as if this functionality must already be in there. Maybe I am just not seeing it.

like image 884
Roland Avatar asked Nov 08 '22 00:11

Roland


1 Answers

What I came up with is the following:

boolean containsSubPath(Path someRealPath, Path subPathToCheck) {
  return someRealPath.normalize()
                     .toString()
                     .contains(subPathToCheck.normalize()
                                             .toString());
}

This way I am able to just call:

containsSubPath(Paths.get("/tmp/some/path/to/somewhere"), Paths.get("some/path"));

As Thomas Kläger pointed out, this solution matches also paths, that are only substrings of a real path (which for my use case would also be ok).

Here is another solution that is probably more correct (for complete matching subpaths), but still not as short as I would like it to be (now corrected due to Kabhals input):

static boolean containsSubPath(Path realPath, Path subPath) {
  for (Path realPathSegment : realPath.normalize()) {
    if (containsSubPath(realPathSegment.iterator(), subPath.normalize().iterator())) {
      return true;
    }
  }
  return false;
}
private static boolean containsSubPath(Iterator<Path> realPathIterator, Iterator<Path> subPathIterator) {
  var hasEntries = realPathIterator.hasNext() && subPathIterator.hasNext();
  while (realPathIterator.hasNext() && subPathIterator.hasNext()) {
    Path realPathSegment = realPathIterator.next();
    Path subPathSegment = subPathIterator.next();
    if (!Objects.equals(realPathSegment, subPathSegment))
      return false;
  }
  return hasEntries;
}

Example calls with expected output:

containsSubPath(Paths.get("/tmp/some/path/to/somewhere"), Paths.get("some/path")) // true
containsSubPath(Paths.get("/tmp/some/path/to/somewhere"), Paths.get("me/pa")) // false

If you need to use it as BinaryOperator just use the method reference instead, i.e. YourClass::containsSubPath.

like image 114
Roland Avatar answered Nov 15 '22 06:11

Roland