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)?



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

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")


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



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);

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;

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);

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));
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.