Path.Combine absolut mit relativen Pfadzeichenfolgen

94

Ich versuche, einen Windows-Pfad mit einem relativen Pfad zu verknüpfen Path.Combine.

Allerdings Path.Combine(@"C:\blah",@"..\bling")gibt C:\blah\..\blingstatt C:\bling\.

Weiß jemand, wie man dies erreicht, ohne meinen eigenen relativen Pfadauflöser zu schreiben (was nicht zu schwer sein sollte)?

CVertex
quelle
5
Wir bekommen hier unterschiedliche Antworten. Ich glaube nicht, dass es ein Duplikat ist
CVertex
1
Es ist doppelt, obwohl ich denke, dass Path.GetFullName eine bessere Lösung ist.
Greg Dean
Du hast dir nur widersprochen. Aber danke für die alternative Antwort.
CVertex
mögliches Duplikat von Path.Combine und der Punktnotation
Julien Bérubé

Antworten:

63

Was funktioniert:

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

(Ergebnis: absolutePath = "C: \ bling.txt")

Was funktioniert nicht?

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

(Ergebnis: absolutePath = "C: /blah/bling.txt")

Llyle
quelle
8
Ja, das ist es, was ich mit der Post unterstelle
Llyle
7
Stellen Sie einfach sicher, dass baseDirectory das abschließende \\ hat, sonst erhalten Sie C:\\blah..\\bling.txtund das funktioniert nicht. In diesem Fall können Sie sie manuell zur Zeichenfolge hinzufügen oder tunPath.GetFullPath(Path.Combine(baseDirectory, relativePath))
Nelson Rothermel
5
Sollte nicht das Ergebnis Ihres Abschnitts " Was funktioniert " sein C:\bling.txt?
cod3monk3y
Warum funktioniert die URI-basierte Methode nicht? Nach dieser Antwort ist das Ergebnis gültig (und es scheint auch unter Windows erkannt zu werden ).
FH
37

Rufen Sie Path.GetFullPath auf dem kombinierten Pfad http://msdn.microsoft.com/en-us/library/system.io.path.getfullpath.aspx auf

> Path.GetFullPath(Path.Combine(@"C:\blah\",@"..\bling"))
C:\bling

(Ich bin damit einverstanden, dass Path.Combine dies selbst tun sollte)

Oberst Panik
quelle
Beachten Sie, dass dies nur funktioniert, wenn der erste Pfad ein absoluter Pfad ist. Es funktioniert nicht fürPath.GetFullPath(Path.Combine(@"..\..\blah",@"\bling"))
derekantrican
16

Path.GetFullPath(@"c:\windows\temp\..\system32")?

shahkalpesh
quelle
2
Hinweis: sollte zuc:\windows\system32
cod3monk3y
4

Für Windows Universal Apps Path.GetFullPath()ist nicht verfügbar, Sie können System.Uristattdessen die Klasse verwenden:

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

Dadurch erhalten Sie genau das, was Sie benötigen (der Pfad muss NICHT vorhanden sein, damit dies funktioniert).

DirectoryInfo di = new DirectoryInfo(@"C:\blah\..\bling");
string cleanPath = di.FullName;
Jonathan Mc Namee
quelle
1
Sowohl Path.GetFullPath () als auch DirectoryInfo.FullName arbeiten mit einem fiktiven Pfad. Das Problem ist, wenn die Datei tatsächlich vorhanden ist, benötigt der ausführende Prozess FileIOPermission - true für beide APIs. (siehe MSDN)
Paul Williams
1

Sei vorsichtig mit Backslashes, vergiss sie nicht (weder zweimal verwenden :)

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

Path.GetFullPath() funktioniert nicht mit relativen Pfaden.

Hier ist die Lösung, die sowohl mit relativen als auch mit absoluten Pfaden funktioniert. Es funktioniert sowohl unter Linux als auch unter Windows und behält das ..erwartete am Anfang des Textes bei (im Ruhezustand werden sie normalisiert). Die Lösung ist immer noch darauf angewiesen Path.GetFullPath, die Korrektur mit einer kleinen Problemumgehung durchzuführen.

Es ist eine Erweiterungsmethode, also benutze sie wie 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));
}
U. Bulle
quelle