Path.Combine absolu avec des chaînes de chemin relatives


94

J'essaie de rejoindre un chemin Windows avec un chemin relatif en utilisant Path.Combine.

Cependant, Path.Combine(@"C:\blah",@"..\bling")renvoie C:\blah\..\blingau lieu de C:\bling\.

Est-ce que quelqu'un sait comment accomplir cela sans écrire mon propre résolveur de chemin relatif (ce qui ne devrait pas être trop difficile)?



5
Nous obtenons des réponses différentes ici ... Je ne pense pas que ce soit un doublon
CVertex

1
c'est en double, même si je pense que Path.GetFullName est une meilleure solution.
Greg Dean

Vous venez de vous contredire. Mais merci pour la réponse alternative.
CVertex

Réponses:


63

Ce qui fonctionne:

string relativePath = "..\\bling.txt";
string baseDirectory = "C:\\blah\\";
string absolutePath = Path.GetFullPath(baseDirectory + relativePath);

(résultat: chemin absolu = "C: \ bling.txt")

Ce qui ne marche pas

string relativePath = "..\\bling.txt";
Uri baseAbsoluteUri = new Uri("C:\\blah\\");
string absolutePath = new Uri(baseAbsoluteUri, relativePath).AbsolutePath;

(résultat: chemin absolu = "C: /blah/bling.txt")


8
Oui, c'est ce que
j'insinue

7
Assurez-vous simplement que baseDirectory a le \\ de fin, sinon vous vous retrouvez avec C:\\blah..\\bling.txtet cela ne fonctionne pas. Dans ce cas, vous pouvez les ajouter manuellement à la chaîne ou fairePath.GetFullPath(Path.Combine(baseDirectory, relativePath))
Nelson Rothermel

5
Le résultat de votre section What Works ne devrait-il pas être C:\bling.txt?
cod3monk3y

Pourquoi la méthode basée sur URI ne fonctionne-t-elle pas? Selon cette réponse , le résultat est valide (et il semble également être reconnu sur Windows ).
FH



4

Pour les applications universelles Windows Path.GetFullPath()ne sont pas disponibles, vous pouvez utiliser la System.Uriclasse à la place:

 Uri uri = new Uri(Path.Combine(@"C:\blah\",@"..\bling"));
 Console.WriteLine(uri.LocalPath);

3

Cela vous donnera exactement ce dont vous avez besoin (le chemin ne doit PAS exister pour que cela fonctionne)

DirectoryInfo di = new DirectoryInfo(@"C:\blah\..\bling");
string cleanPath = di.FullName;

1
Path.GetFullPath () et DirectoryInfo.FullName fonctionneront sur un chemin fictif. Le problème est que lorsque le fichier existe réellement, le processus d'exécution a besoin de FileIOPermission - vrai pour les deux API. (voir MSDN)
Paul Williams

1

Faites attention aux backslashes, ne les oubliez pas (ne les utilisez pas deux fois :)

string relativePath = "..\\bling.txt";
string baseDirectory = "C:\\blah\\";
//OR:
//string relativePath = "\\..\\bling.txt";
//string baseDirectory = "C:\\blah";
//THEN
string absolutePath = Path.GetFullPath(baseDirectory + relativePath);

0

Path.GetFullPath() ne fonctionne pas avec les chemins relatifs.

Voici la solution qui fonctionne avec les deux chemins relatifs + absolus. Il fonctionne à la fois sous Linux + Windows et il garde le ..comme prévu au début du texte (au repos, ils seront normalisés). La solution repose toujours sur Path.GetFullPathle correctif avec une petite solution de contournement.

C'est une méthode d'extension alors utilisez-la comme text.Canonicalize()

/// <summary>
///     Fixes "../.." etc
/// </summary>
public static string Canonicalize(this string path)
{
    if (path.IsAbsolutePath())
        return Path.GetFullPath(path);
    var fakeRoot = Environment.CurrentDirectory; // Gives us a cross platform full path
    var combined = Path.Combine(fakeRoot, path);
    combined = Path.GetFullPath(combined);
    return combined.RelativeTo(fakeRoot);
}
private static bool IsAbsolutePath(this string path)
{
    if (path == null) throw new ArgumentNullException(nameof(path));
    return
        Path.IsPathRooted(path)
        && !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)
        && !Path.GetPathRoot(path).Equals(Path.AltDirectorySeparatorChar.ToString(), StringComparison.Ordinal);
}
private static string RelativeTo(this string filespec, string folder)
{
    var pathUri = new Uri(filespec);
    // Folders must end in a slash
    if (!folder.EndsWith(Path.DirectorySeparatorChar.ToString())) folder += Path.DirectorySeparatorChar;
    var folderUri = new Uri(folder);
    return Uri.UnescapeDataString(folderUri.MakeRelativeUri(pathUri).ToString()
        .Replace('/', Path.DirectorySeparatorChar));
}
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.