2017-03-20 1 views
0

J'ai besoin de vérifier si un chemin donné est un sous-chemin n'importe où dans un autre chemin et je me demandais s'il existe déjà une telle méthode avant d'écrire la mienne.java.nio.file.Path.contains (sous-chemin)?

Voici un code qui peut aider à comprendre le problème:

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 

Je l'ai déjà vu relativize, mais je ne pense pas que ce soit la meilleure façon de résoudre le problème. Le plus simple que j'ai trouvé était normalize().toString().contains(/* other normalized string path */). Mais peut-être y a-t-il un moyen plus facile? Beaucoup de méthodes à l'intérieur Paths semblent comme si cette fonctionnalité doit déjà être là. Peut-être que je ne le vois tout simplement pas.

Répondre

0

Ce que je suis venu avec est la suivante:

BiPredicate<Path, Path> containsSubPath = 
    (someRealPath, subPathToCheck) -> someRealPath.normalize() 
                .toString() 
                .contains(subPathToCheck.normalize() 
                      .toString()) 

De cette façon, je peux appeler simplement:

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

Comme Thomas Kläger a souligné, cette solution correspond aussi des chemins, qui sont Seules les sous-chaînes d'un chemin réel (ce qui serait également acceptable pour mon utilisation).

Voici une autre solution qui est probablement plus correct (pour les sous-chemins correspondants complets), mais toujours pas aussi court que je voudrais que ce soit:

BiPredicate<Path, Path> containsSubPath = (realPath, subPath) -> { 
    Iterator<Path> realPathIterator = realPath.normalize().iterator(); 
    Iterator<Path> subPathIterator = subPath.normalize().iterator(); 

    while (realPathIterator.hasNext()) { 
    Path realPathSegment = realPathIterator.next(); 
    if (subPathIterator.hasNext()) { 
     Path subPathSegment = subPathIterator.next(); 
     if (!Objects.equals(realPathSegment, subPathSegment)) { 
     subPathIterator = subPath.normalize().iterator(); 
     } 
    } else { 
     break; 
    } 
    } 
    return !subPathIterator.hasNext(); 
}; 

Exemple appelle avec une sortie prévue:

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

Vous ne savez pas si votre solution est correcte. 'containsSubPath.test (Paths.get ("/tmp/un/chemin/vers/quelque part "), Paths.get (" me/pa "))' donne également vrai, mais je m'attendrais à ce qu'il renvoie false. –

+0

Merci d'avoir signalé! pour mon cas d'utilisation ce serait bien car je connais tout le sous-chemin qui doit être trouvé et je sais aussi qu'il n'existe pas de sous-chemins partiels similaires ;-) cependant s'il y a une solution plus complète (et correcte), qui peut gérer des sous-chemins complets, ce serait encore mieux. Joué aussi avec 'Path.subpath' combiné avec un' IntStream', mais cela semble plutôt compliqué pour un problème si facile. Peut-être que 'Path.normalize(). Iterator' est la solution la plus simple et la plus complète. – Roland