web-dev-qa-db-fra.com

Conversion de chemins relatifs en chemins absolus

J'ai un chemin absolu vers le fichier A.

J'ai un chemin relatif au fichier B à partir du répertoire du fichier A. Ce chemin peut et va utiliser ".." pour remonter la structure de répertoires de manière arbitrairement complexe.

Exemple A:

  • C:\projects\project1\module7\submodule5\fileA

Exemple Bs:

  • ..\..\module3\submodule9\subsubmodule32\fileB
  • ..\submodule5\fileB
  • ..\..\module7\..\module4\submodule1\fileB
  • fileB

Comment combiner les deux pour obtenir le chemin le plus simple chemin absolu vers le fichier B?

30
Tom Tresansky

Si je comprends bien votre problème, vous pouvez faire quelque chose comme ceci:

File a = new File("/some/abs/path");
File parentFolder = new File(a.getParent());
File b = new File(parentFolder, "../some/relative/path");
String absolute = b.getCanonicalPath(); // may throw IOException
40
Fabian Steeg

Dans Java 7, vous pouvez également utiliser l’interface Path :

Path basePath = FileSystems.getDefault().getPath("C:\\projects\\project1\\module7\\submodule5\\fileA");
Path resolvedPath = basePath.getParent().resolve("..\\..\\module3\\submodule9\\subsubmodule32\\fileB"); // use getParent() if basePath is a file (not a directory) 
Path abolutePath = resolvedPath.normalize();
14
onlyhuman

String absolutePath = FileSystems.getDefault (). GetPath (mayBeRelativePath) .normalize (). ToAbsolutePath (). ToString ();

7
rssdev10
3
yegor256

Quoi de mieux que de créer un utilitaire qui convertit les chemins d'accès relatifs en chemins absolus, c'est de créer un utilitaire qui convertit tout chemin qui lui est transmis en chemin absolu, de sorte que vous n'ayez pas à vérifier côté client.

Le code ci-dessous fonctionne pour moi dans les deux cas et j'ai utilisé le type String à la signature de la méthode (paramètre et valeur de retour):

public static String toAbsolutePath(String maybeRelative) {
    Path path = Paths.get(maybeRelative);
    Path effectivePath = path;
    if (!path.isAbsolute()) {
        Path base = Paths.get("");
        effectivePath = base.resolve(path).toAbsolutePath();
    }
    return effectivePath.normalize().toString();
}

Changer le code ci-dessus pour exposer les types Path sur la signature de la méthode est trivial (et en fait plus facile), mais je pense que l'utilisation de String sur la signature donne plus de flexibilité.

1

Voici l'exemple de code qui fonctionne pour moi.

 public String absolutePath(String relative, String absoluteTo)
    {       
        String[] absoluteDirectories = relative.split("\\\\");
        String[] relativeDirectories = absoluteTo.split("\\\\");
        int relativeLength = relativeDirectories.length;
        int absoluteLength = absoluteDirectories.length; 
        int lastCommonRoot = 0;
        int index;
        for (index = 0; index < relativeLength; index++)
            if (relativeDirectories[index].equals("..\\\\"))
                lastCommonRoot = index;
            else
                break;
        StringBuilder absolutePath = new StringBuilder();
        for (index = 0; index < absoluteLength - lastCommonRoot; index++)
        {  
             if (absoluteDirectories[index].length() > 0) 
                 absolutePath.append(absoluteDirectories[index] + "\\\\");                          
        }
        for (index = lastCommonRoot; index < relativeLength  - lastCommonRoot; 
                                                               index++)
        {  
             if (relativeDirectories[index].length() > 0) 
                 absolutePath.append(relativeDirectories[index] + "\\\\");                          
        }
        return absolutePath.toString();              
    }

Aussi je la conversion au parent:

public String relativePath(String absolute, String relativeTo) throws Exception
    {       
        String[] absoluteDirectories = absolute.split("\\\\");
        String[] relativeDirectories = relativeTo.split("\\\\");
        int length = absoluteDirectories.length < relativeDirectories.length ?
                        absoluteDirectories.length : relativeDirectories.length;
        int lastCommonRoot = -1;
        int index;
        for (index = 0; index < length; index++)
            if (absoluteDirectories[index].equals(relativeDirectories[index]))
                lastCommonRoot = index;
            else
                break;
        if (lastCommonRoot > -1){
            StringBuilder relativePath = new StringBuilder();
            for (index = lastCommonRoot + 1; index <absoluteDirectories.length;
                                                                         index++)
                if (absoluteDirectories[index].length() > 0)
                    relativePath.append("..\\\\");
            for (index = lastCommonRoot + 1; index <relativeDirectories.length-1;
                                                                         index++)
                relativePath.append(relativeDirectories[index] + "\\\\");
            relativePath.append(relativeDirectories[relativeDirectories.length - 1]);
            return relativePath.toString();         
        }
        else{
            throw new Exception("No common root found between working direcotry and filename");
        }            
    }
0
iviorel

Je sais que ce n'est pas la meilleure solution, mais vous ne pouvez pas combiner simplement la sous-chaîne du chemin de fichierA de 0 à lastIndexOf("\") avec le chemin de fichierB. 

Exemple A:

  • C:\projects\project1\module7\submodule5\fileA

Exemple Bs:

  • ..\..\module3\submodule9\subsubmodule32\fileB

C:\projects\project1\module7\submodule5\..\..\module3\submodule9\subsubmodule32\fileB

Si vous ne voulez pas que le .. soit là, cela prendrait plus de temps, mais je vous recommande de suivre le chemin pour fileB et de continuer à prendre la sous-chaîne de 0 au premier index de \. Puis vérifiez la sous-chaîne. S'il s'agit de .., supprimez la sous-chaîne et la sous-chaîne de fileA's path de lastIndexOf(\) à length. Alors répète. De cette façon, vous supprimez les dossiers inutiles et le ..s.

Alors : 

Exemple A:

  • C:\projects\project1\module7\submodule5\fileA

Exemple Bs:

  • ..\..\module3\submodule9\subsubmodule32\fileB

    -> C:\projects\project1\module3\submodule9\subsubmodule32\fileB

0
Kyra