Comment convertir un chemin relatif en chemin absolu dans une application Windows?


89

Comment convertir un chemin relatif en chemin absolu dans une application Windows?

Je sais que nous pouvons utiliser server.MapPath () dans ASP.NET. Mais que pouvons-nous faire dans une application Windows?

Je veux dire, s'il existe une fonction intégrée .NET qui peut gérer cela ...


2
Voulez-vous dire un chemin relatif vers le répertoire courant, en d'autres termes le répertoire de travail, ou relatif à l'emplacement du .exe?
Tobias Hertkorn

2
Il existe deux types de chemins relatifs. Un si de la forme "A \ B \ C" et n'implique pas une base particulière. L'autre a la forme ". \ A \ B" ou ".. \ A \ B"; ceux-ci sont relatifs au répertoire de travail actuel.
MSalters le

1
@Amit Dhall: Au fait, c'est une bonne chose d'accepter et de voter pour la ou les réponses qui vous aident.
Francis B.

Réponses:


180

As-tu essayé:

string absolute = Path.GetFullPath(relative);

? Notez que cela utilisera le répertoire de travail actuel du processus, pas le répertoire contenant l'exécutable. Si cela ne vous aide pas, veuillez clarifier votre question.


3
Cela ne dépendrait-il pas de l'endroit où vous démarrez l'application, pas de l'endroit où se trouve l'exe? Certes, la question n'est pas vraiment claire à ce sujet.
Tobias Hertkorn

1
Comme vous le dites, la question n'est pas claire. GetFullPath résoudra à partir du répertoire de travail actuel. Je modifierai ma réponse pour l'indiquer.
Jon Skeet le

1
Si une application est lancée via l'Explorateur Windows, il semble que le répertoire en cours et le répertoire de l'assembly en cours d'exécution soient les mêmes (au moins jusqu'à ce que quelque chose soit fait pour les rendre différents). Cela est vrai même si vous utilisez un raccourci vers l'exécutable où le raccourci se trouve dans un endroit complètement différent.
H2ONaCl

19

Si vous souhaitez obtenir le chemin relatif à votre .exe, utilisez

string absolute = Path.Combine(Application.ExecutablePath, relative);

4
Soyez prudent avec Path.Combine. Si la partie «relative» commence par une barre oblique, elle peut ne pas faire ce que vous pensez qu'elle ferait.
Noon Silk

2
@silky: eh bien, alors ce n'est pas relatif, n'est-ce pas?
Tor Haugen le

1
Semble Path.Combinene peut même pas gérer les chemins relatifs aux lecteurs. Il ignore simplement le chemin initial qu'il semble. Je publie ma propre solution complète.
Nyerguds

3
Cela ne peut pas gérer un chemin relatif. Il n'accepte qu'un répertoire et un nom de fichier. Si le deuxième argument commence par quelque chose comme .., cela produira des déchets.
Jonathan Wood

1
@JonathanWood En fait, ce "garbage" (les chemins qui les incluent ..) est parfaitement accepté et résolu par tous les systèmes de manipulation de fichiers dans .Net. Si cela vous dérange, exécutez- absolute = Path.GetFullPath(absolute)le.
Nyerguds

16

Celui-ci fonctionne pour les chemins sur différents lecteurs, pour les chemins relatifs aux lecteurs et pour les chemins relatifs réels. Heck, cela fonctionne même si le basePathn'est pas vraiment absolu; il utilise toujours le répertoire de travail actuel comme solution de secours finale.

public static String GetAbsolutePath(String path)
{
    return GetAbsolutePath(null, path);
}

public static String GetAbsolutePath(String basePath, String path)
{
    if (path == null)
        return null;
    if (basePath == null)
        basePath = Path.GetFullPath("."); // quick way of getting current working directory
    else
        basePath = GetAbsolutePath(null, basePath); // to be REALLY sure ;)
    String finalPath;
    // specific for windows paths starting on \ - they need the drive added to them.
    // I constructed this piece like this for possible Mono support.
    if (!Path.IsPathRooted(path) || "\\".Equals(Path.GetPathRoot(path)))
    {
        if (path.StartsWith(Path.DirectorySeparatorChar.ToString()))
            finalPath = Path.Combine(Path.GetPathRoot(basePath), path.TrimStart(Path.DirectorySeparatorChar));
        else
            finalPath = Path.Combine(basePath, path);
    }
    else
        finalPath = path;
    // resolves any internal "..\" to get the true full path.
    return Path.GetFullPath(finalPath);
}

1
Excellente solution car il combine un chemin absolu ou relatif selon un chemin de base. À mon avis, l'argument relativePath devrait être renommé AbsoluteOrRelativePath, car c'est ce qu'il représente vraiment. Merci
Julio Nobre

1
Eh bien, si c'est déjà un chemin absolu, c'est juste un cas spécial, vraiment ... la fonction est toujours destinée à résoudre les chemins relatifs, lol. Je viens de le nommer ici pour préciser quel paramètre est lequel;)
Nyerguds

1
@JulioNobre d'autant plus que les arguments ici sont inversés par rapport à Path.Combine. C'est facilement corrigé, mais je l'évite car je l'utilise souvent pour résoudre les chemins relatifs sur le répertoire de travail, et donner null comme premier argument semble bizarre.
Nyerguds

1
J'apprécie vos conseils, mais je n'ai l'intention d'utiliser cette aide que lorsque j'ai besoin de combiner un chemin de base avec un autre chemin qui peut être soit relatif à ce chemin de base, soit absolu. C'est pourquoi j'ai préféré adopter la signature suivante: GetAbsolutePath (String BasePath, String RelativeOrAbsolutePath). Si un argument est nul, une exception est levée pour renforcer le fait que les deux sont obligatoires pour utiliser cette méthode. Encore une fois, merci :-)
Julio Nobre

2
Ouais, c'est raisonnable. On ne peut pas se donner la peine de modifier ceci juste pour jongler avec certains arguments.
Nyerguds

2

C'est un sujet un peu plus ancien, mais cela pourrait être utile pour quelqu'un. J'ai résolu un problème similaire, mais dans mon cas, le chemin n'était pas au début du texte.

Voici donc ma solution:

public static class StringExtension
{
    private const string parentSymbol = "..\\";
    private const string absoluteSymbol = ".\\";
    public static String AbsolutePath(this string relativePath)
    {
        string replacePath = AppDomain.CurrentDomain.BaseDirectory;
        int parentStart = relativePath.IndexOf(parentSymbol);
        int absoluteStart = relativePath.IndexOf(absoluteSymbol);
        if (parentStart >= 0)
        {
            int parentLength = 0;
            while (relativePath.Substring(parentStart + parentLength).Contains(parentSymbol))
            {
                replacePath = new DirectoryInfo(replacePath).Parent.FullName;
                parentLength = parentLength + parentSymbol.Length;
            };
            relativePath = relativePath.Replace(relativePath.Substring(parentStart, parentLength), string.Format("{0}\\", replacePath));
        }
        else if (absoluteStart >= 0)
        {
            relativePath = relativePath.Replace(".\\", replacePath);
        }
        return relativePath;
    }
}

Exemple:

Data Source=.\Data\Data.sdf;Persist Security Info=False;
Data Source=..\..\bin\Debug\Data\Data.sdf;Persist Security Info=False;

1
Hum. Vous réinventez la roue. Path.GetFullPathrésout. \ et .. \ automatiquement. De plus, vous ajoutez la AbsolutePathfonction d'extension à la classe String en général ... peut être un peu exagéré.
Nyerguds le

1
Ai-je tort de dire que Path.GetFullPath considère toujours le répertoire de base comme le répertoire actuel de l'AppDomain de l'application. Dans ce cas, Path.GetFullPath ne peut pas renvoyer le chemin complet à partir d'un répertoire différent. L'algorithme suivant, cependant, prend cela en considération ... Je veux dire, il vous suffit d'ajouter un autre paramètre facultatif qui remplacerait le CurrentDomainDirectory.
Samuel
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.