Wie konvertiere ich einen relativen Pfad in einen absoluten Pfad in einer Windows-Anwendung?

89

Wie konvertiere ich einen relativen Pfad in einen absoluten Pfad in einer Windows-Anwendung?

Ich weiß, dass wir server.MapPath () in ASP.NET verwenden können. Aber was können wir in einer Windows-Anwendung tun?

Ich meine, wenn es eine in .NET integrierte Funktion gibt, die damit umgehen kann ...

Amit Dhall
quelle
2
Meinen Sie einen relativen Pfad zum aktuellen Verzeichnis, dh zum Arbeitsverzeichnis, oder relativ zum Speicherort der EXE-Datei?
Tobias Hertkorn
2
Es gibt zwei Arten von relativen Pfaden. Eine, wenn sie die Form "A \ B \ C" hat und keine bestimmte Basis impliziert. Der andere hat die Form ". \ A \ B" oder ".. \ A \ B"; Diese beziehen sich auf das aktuelle Arbeitsverzeichnis.
MSalters
1
@Amit Dhall: Übrigens ist es gut, die Antwort (en), die Ihnen helfen, zu akzeptieren und zu bewerten.
Francis B.

Antworten:

179

Hast du es versucht:

string absolute = Path.GetFullPath(relative);

? Beachten Sie, dass dabei das aktuelle Arbeitsverzeichnis des Prozesses verwendet wird, nicht das Verzeichnis, das die ausführbare Datei enthält. Wenn das nicht hilft, klären Sie bitte Ihre Frage.

Jon Skeet
quelle
3
Wäre das nicht abhängig davon, wo Sie die App starten, nicht davon, wo sich die Exe befindet? Zugegeben, die Frage ist dazu nicht wirklich klar.
Tobias Hertkorn
1
Wie Sie sagen, ist die Frage nicht klar. GetFullPath wird aus dem aktuellen Arbeitsverzeichnis aufgelöst. Ich werde meine Antwort bearbeiten, um dies anzuzeigen.
Jon Skeet
1
Wenn eine Anwendung über Windows Explorer gestartet wird, scheinen das aktuelle Verzeichnis und das ausführende Assemblyverzeichnis identisch zu sein (zumindest bis etwas unternommen wird, um sie voneinander zu unterscheiden). Dies gilt auch dann, wenn Sie eine Verknüpfung zur ausführbaren Datei verwenden, in der sich die Verknüpfung an einem völlig anderen Ort befindet.
H2ONaCl
19

Wenn Sie den Pfad relativ zu Ihrer EXE-Datei erhalten möchten, verwenden Sie

string absolute = Path.Combine(Application.ExecutablePath, relative);
Tobias Hertkorn
quelle
4
Sei einfach vorsichtig mit Path.Combine. Wenn der 'relative' Teil mit einem Schrägstrich beginnt, kann es sein, dass er nicht das tut, was Sie denken.
Mittag Seide
2
@silky: na dann ist es doch nicht relativ, oder?
Tor Haugen
1
Scheint Path.Combinenicht einmal mit fahrzeugbezogenen Pfaden umgehen zu können. Es ignoriert einfach den anfänglichen Pfad, wie es scheint. Ich poste meine eigene vollständige Lösung.
Nyerguds
3
Dies kann keinen relativen Pfad verarbeiten. Es werden nur ein Verzeichnis und ein Dateiname akzeptiert. Wenn das zweite Argument mit etwas Ähnlichem beginnt .., wird Müll erzeugt.
Jonathan Wood
1
@JonathanWood Tatsächlich wird dieser "Müll" (Pfade, die darin enthalten ..sind) von allen Dateimanipulationssystemen in .Net perfekt akzeptiert und aufgelöst. Wenn es Sie stört, führen Sie absolute = Path.GetFullPath(absolute)es aus.
Nyerguds
15

Dieser funktioniert für Pfade auf verschiedenen Laufwerken, für Laufwerksrelative Pfade und für tatsächliche relative Pfade. Heck, es funktioniert sogar, wenn das basePathnicht wirklich absolut ist; Es verwendet immer das aktuelle Arbeitsverzeichnis als endgültigen Fallback.

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);
}
Nyerguds
quelle
1
Tolle Lösung, da entweder der absolute Pfad oder der Verwandtschaftspfad gemäß einem Basispfad kombiniert wird. Meiner Meinung nach sollte das relativePath-Argument in AbsoluteOrRelativePath umbenannt werden, da es das ist, was es wirklich darstellt. Vielen Dank
Julio Nobre
1
Nun, wenn es bereits ein absoluter Pfad ist, ist das wirklich nur ein Sonderfall ... die Funktion ist immer noch dazu gedacht, relative Pfade aufzulösen, lol. Ich habe es hier nur so genannt, um zu verdeutlichen, welcher Parameter welcher ist;)
Nyerguds
1
@ JulioNobre zumal die Argumente hier im Vergleich zu umgekehrt sind Path.Combine. Das ist leicht zu beheben, aber ich vermeide es, da ich es oft verwende, um relative Pfade im Arbeitsverzeichnis aufzulösen, und null als erstes Argument anzugeben, sieht seltsam aus.
Nyerguds
1
Ich schätze Ihren Rat, aber ich beabsichtige nur, diesen Helfer zu verwenden, wenn ich einen Basispfad mit einem anderen Pfad kombinieren muss, der entweder relativ zu diesem Basispfad oder absolut sein kann. Aus diesem Grund habe ich es vorgezogen, die folgende Signatur zu verwenden: GetAbsolutePath (String BasePath, String RelativeOrAbsolutePath). Wenn ein Argument null ist, wird eine Ausnahme ausgelöst, um zu bestätigen, dass beide für die Verwendung dieser Methode obligatorisch sind. Nochmals vielen Dank :-)
Julio Nobre
2
Ja, das ist sinnvoll. Ich kann mir nicht die Mühe machen, dies zu bearbeiten, nur um ein paar Argumente zu jonglieren.
Nyerguds
2

Es ist ein etwas älteres Thema, aber es könnte für jemanden nützlich sein. Ich habe ein ähnliches Problem gelöst, aber in meinem Fall befand sich der Pfad nicht am Anfang des Textes.

Also hier ist meine Lösung:

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

Beispiel:

Data Source=.\Data\Data.sdf;Persist Security Info=False;
Data Source=..\..\bin\Debug\Data\Data.sdf;Persist Security Info=False;
vesi
quelle
1
Äh. Sie erfinden das Rad neu. Path.GetFullPathwird automatisch aufgelöst. \ und .. \. Außerdem fügen Sie die AbsolutePathErweiterungsfunktion der String-Klasse im Allgemeinen hinzu. Dies kann etwas übertrieben sein.
Nyerguds
1
Bin ich falsch zu sagen, dass Path.GetFullPath das Basisverzeichnis immer als das aktuelle Verzeichnis der AppDomain der Anwendung betrachtet. In diesem Fall kann Path.GetFullPath nicht den vollständigen Pfad aus einem anderen Verzeichnis zurückgeben. Der folgende Algorithmus berücksichtigt dies jedoch ... Ich meine, Sie müssen nur einen weiteren optionalen Parameter hinzufügen, der das CurrentDomainDirectory ersetzen würde.
Samuel