Überprüfen Sie, ob der vollständige Pfad angegeben ist

104

Gibt es eine Methode, um zu überprüfen, ob der angegebene Pfad der vollständige Pfad ist? Im Moment mache ich das:

if (template.Contains(":\\")) //full path already given
{
}
else //calculate the path from local assembly
{
}

Aber es muss einen eleganteren Weg geben, dies zu überprüfen?

hs2d
quelle

Antworten:

141

Versuchen Sie es mit System.IO.Path.IsPathRooted? Es wird auch truefür absolute Pfade zurückgegeben.

System.IO.Path.IsPathRooted(@"c:\foo"); // true
System.IO.Path.IsPathRooted(@"\foo"); // true
System.IO.Path.IsPathRooted("foo"); // false

System.IO.Path.IsPathRooted(@"c:1\foo"); // surprisingly also true
System.IO.Path.GetFullPath(@"c:1\foo");// returns "[current working directory]\1\foo"
Detaylor
quelle
14
Wie kommt es, dass das zweite Beispiel ein absoluter Weg ist?
Om471987
3
Der zweite Pfad ist nicht absolut, jedoch verwurzelt. Der führende Schrägstrich gibt die Wurzel des Systems an.
Detaylor
3
@SmirkinGherkin Was ist der Unterschied zwischen einem verwurzelten und einem absoluten Pfad?
Jason Axelson
1
In meiner Antwort ( stackoverflow.com/a/35046453/704808 ) finden Sie eine Alternative, die einen vollständigen Pfad gewährleistet und gleichzeitig die folgenden Vorteile bietet IsPathRooted: Vermeiden des Zugriffs auf das Dateisystem oder Auslösen von Ausnahmen für ungültige Eingaben.
Wehr
1
@daniel, IIRC Es wurde aufgenommen, um zu zeigen, dass der Pfad kein gültiger Pfad sein muss, um verwendet zu IsPathRootedwerden. Es war sicherlich nichts Bedeutendes. Die GetFullPathLinie wurde aufgenommen, damit der zu bewertende Pfad beobachtet werden konnte
Detaylor
30
Path.IsPathRooted(path)
&& !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)

Die obige Bedingung:

  • erfordert keine Dateisystemberechtigungen
  • Gibt falsein den meisten Fällen zurück, in denen das Format von pathungültig ist (anstatt eine Ausnahme auszulösen).
  • Gibt truenur zurück, wenn pathdas Volume enthalten ist

In Szenarien wie dem des OP ist es daher möglicherweise besser geeignet als die Bedingungen in den früheren Antworten. Im Gegensatz zu der oben genannten Bedingung:

  • path == System.IO.Path.GetFullPath(path)löst falsein diesen Szenarien Ausnahmen aus, anstatt zurückzukehren :
    • Der Anrufer verfügt nicht über die erforderlichen Berechtigungen
    • Das System konnte den absoluten Pfad nicht abrufen
    • Der Pfad enthält einen Doppelpunkt (":"), der nicht Teil einer Datenträgerkennung ist
    • Der angegebene Pfad, Dateiname oder beide überschreiten die vom System definierte maximale Länge
  • System.IO.Path.IsPathRooted(path)Gibt zurück, truewenn pathmit einem einzelnen Verzeichnistrennzeichen begonnen wird.

Schließlich ist hier eine Methode, die die obige Bedingung umschließt und auch die verbleibenden möglichen Ausnahmen ausschließt:

public static bool IsFullPath(string path) {
    return !String.IsNullOrWhiteSpace(path)
        && path.IndexOfAny(System.IO.Path.GetInvalidPathChars().ToArray()) == -1
        && Path.IsPathRooted(path)
        && !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal);
}

EDIT: EM0 machte einen guten Kommentar und eine alternative Antwort auf den merkwürdigen Fall von Pfaden wie C:und C:dir. Um zu entscheiden, wie Sie mit solchen Pfaden umgehen möchten, sollten Sie sich eingehend mit MSDN -> Windows-Desktopanwendungen -> Entwickeln -> Desktop-Technologien -> Datenzugriff und -speicherung -> Lokale Dateisysteme - befassen. -> Dateiverwaltung -> Informationen zur Dateiverwaltung -> Erstellen, Löschen und Verwalten von Dateien -> Benennen von Dateien, Pfaden und Namespaces -> Vollständig qualifizierte oder relative Pfade

Bei Windows-API-Funktionen, die Dateien bearbeiten, können Dateinamen häufig relativ zum aktuellen Verzeichnis sein, während für einige APIs ein vollständig qualifizierter Pfad erforderlich ist. Ein Dateiname ist relativ zum aktuellen Verzeichnis, wenn er nicht mit einem der folgenden Elemente beginnt:

  • Ein UNC-Name eines beliebigen Formats, der immer mit zwei Backslash-Zeichen ("\") beginnt. Weitere Informationen finden Sie im nächsten Abschnitt.
  • Ein Datenträgerbezeichner mit einem Backslash, z. B. "C:" oder "d:".
  • Ein einzelner Backslash, z. B. "\ directory" oder "\ file.txt". Dies wird auch als absoluter Pfad bezeichnet.

Wenn ein Dateiname nur mit einem Festplattenbezeichner beginnt, nicht jedoch mit dem Backslash nach dem Doppelpunkt, wird er als relativer Pfad zum aktuellen Verzeichnis auf dem Laufwerk mit dem angegebenen Buchstaben interpretiert. Beachten Sie, dass das aktuelle Verzeichnis möglicherweise das Stammverzeichnis ist oder nicht, je nachdem, auf was es während des letzten Vorgangs "Verzeichnis ändern" auf dieser Festplatte eingestellt wurde. Beispiele für dieses Format sind:

  • "C: tmp.txt" bezieht sich auf eine Datei mit dem Namen "tmp.txt" im aktuellen Verzeichnis auf Laufwerk C.
  • "C: tempdir \ tmp.txt" bezieht sich auf eine Datei in einem Unterverzeichnis des aktuellen Verzeichnisses auf Laufwerk C.

[...]

Wehr
quelle
3
Ich mag es, dass dies nicht für ungültige Pfade auslöst, sondern true für Pfade wie "C:" und "C: dir" zurückgibt, die von GetFullPath unter Verwendung des aktuellen Verzeichnisses aufgelöst werden (sie sind also nicht absolut). Hat eine Antwort gepostet, die für diese falsch zurückgibt.
EM0
@ EM0 - Danke! Du hast mir gerade etwas beigebracht. :)
Wehr
15

Versuchen

System.IO.Path.IsPathRooted(template)

Funktioniert sowohl für UNC-Pfade als auch für lokale.

Z.B

Path.IsPathRooted(@"\\MyServer\MyShare\MyDirectory")  // returns true
Path.IsPathRooted(@"C:\\MyDirectory")  // returns true
Joe
quelle
13

Alte Frage, aber noch eine zutreffende Antwort. Wenn Sie sicherstellen möchten, dass das Volume in einem lokalen Pfad enthalten ist, können Sie System.IO.Path.GetFullPath () wie folgt verwenden:

if (template == System.IO.Path.GetFullPath(template))
{
    ; //template is full path including volume or full UNC path
}
else
{
    if (useCurrentPathAndVolume)
        template = System.IO.Path.GetFullPath(template);
    else
        template = Assembly.GetExecutingAssembly().Location
}
GreggD
quelle
3
Dies war das, was ich brauchte und scheint näher an der ursprünglichen Frage zu sein, da IsPathRooted 'für relative Pfade (nicht unbedingt absolute Pfade)
true zurückgibt
GetFullPathgreift auf das Dateisystem zu und kann eine Reihe möglicher Ausnahmen auslösen. In meiner Antwort ( stackoverflow.com/a/35046453/704808 ) finden Sie eine Alternative, die weiterhin einen vollständigen Pfad gewährleistet.
Wehr
11

Aufbauend auf der Antwort von Weir : Dies führt nicht zu ungültigen Pfaden, sondern auch falsezu Pfaden wie "C:", "C: dirname" und "\ path".

public static bool IsFullPath(string path)
{
    if (string.IsNullOrWhiteSpace(path) || path.IndexOfAny(Path.GetInvalidPathChars()) != -1 || !Path.IsPathRooted(path))
        return false;

    string pathRoot = Path.GetPathRoot(path);
    if (pathRoot.Length <= 2 && pathRoot != "/") // Accepts X:\ and \\UNC\PATH, rejects empty string, \ and X:, but accepts / to support Linux
        return false;

    if (pathRoot[0] != '\\' || pathRoot[1] != '\\')
        return true; // Rooted and not a UNC path

    return pathRoot.Trim('\\').IndexOf('\\') != -1; // A UNC server name without a share name (e.g "\\NAME" or "\\NAME\") is invalid
}

Beachten Sie, dass dies unter Windows und Linux unterschiedliche Ergebnisse zurückgibt, z. B. "/ path" ist unter Linux absolut, aber nicht unter Windows.

Gerätetest:

[Test]
public void IsFullPath()
{
    bool isWindows = Environment.OSVersion.Platform.ToString().StartsWith("Win"); // .NET Framework
    // bool isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows); // .NET Core

    // These are full paths on Windows, but not on Linux
    TryIsFullPath(@"C:\dir\file.ext", isWindows);
    TryIsFullPath(@"C:\dir\", isWindows);
    TryIsFullPath(@"C:\dir", isWindows);
    TryIsFullPath(@"C:\", isWindows);
    TryIsFullPath(@"\\unc\share\dir\file.ext", isWindows);
    TryIsFullPath(@"\\unc\share", isWindows);

    // These are full paths on Linux, but not on Windows
    TryIsFullPath(@"/some/file", !isWindows);
    TryIsFullPath(@"/dir", !isWindows);
    TryIsFullPath(@"/", !isWindows);

    // Not full paths on either Windows or Linux
    TryIsFullPath(@"file.ext", false);
    TryIsFullPath(@"dir\file.ext", false);
    TryIsFullPath(@"\dir\file.ext", false);
    TryIsFullPath(@"C:", false);
    TryIsFullPath(@"C:dir\file.ext", false);
    TryIsFullPath(@"\dir", false); // An "absolute", but not "full" path

    // Invalid on both Windows and Linux
    TryIsFullPath(null, false, false);
    TryIsFullPath("", false, false);
    TryIsFullPath("   ", false, false);
    TryIsFullPath(@"C:\inval|d", false, false);
    TryIsFullPath(@"\\is_this_a_dir_or_a_hostname", false, false);
    TryIsFullPath(@"\\is_this_a_dir_or_a_hostname\", false, !isWindows);
    TryIsFullPath(@"\\is_this_a_dir_or_a_hostname\\", false, !isWindows);
}

private static void TryIsFullPath(string path, bool expectedIsFull, bool expectedIsValid = true)
{
    Assert.AreEqual(expectedIsFull, PathUtils.IsFullPath(path), "IsFullPath('" + path + "')");

    if (expectedIsFull)
    {
        Assert.AreEqual(path, Path.GetFullPath(path));
    }
    else if (expectedIsValid)
    {
        Assert.AreNotEqual(path, Path.GetFullPath(path));
    }
    else
    {
        Assert.That(() => Path.GetFullPath(path), Throws.Exception);
    }
}
EM0
quelle
Gutes Zeug. Ich habe festgestellt , dass msdn.microsoft.com/en-us/library/windows/desktop/… angibt, dass ein Pfad unter Windows nicht relativ ist, wenn er mit "Ein einzelner Backslash"
Wehr
1
Guter Punkt! Sieht aus wie meine Terminologie war aus. Als ich "absoluter Pfad" sagte, dachte ich wirklich darüber nach, was MS einen "vollständigen Pfad" nennt. Ich habe den Namen geändert und einen Testfall hinzugefügt.
EM0
1
Danke für diese Antwort, es hat mir sehr geholfen. Beachten Sie jedoch, dass für einen UNC-Pfad wie \\ Server \ die Methode true zurückgibt. Dies löst jedoch eine Ausnahme aus, wenn Sie Directory.Exists (Pfad) aufrufen (System.ArgumentException: 'Der UNC-Pfad sollte die Form haben \\ server \ share. ')
Carl
2
Schön zu sehen, dass die Leute dies immer noch verwenden und neue Randfälle finden @Carl Den Code aktualisiert und darauf getestet!
EM0
6

So überprüfen Sie, ob ein Pfad vollständig qualifiziert ist (MSDN) :

public static bool IsPathFullyQualified(string path)
{
    var root = Path.GetPathRoot(path);
    return root.StartsWith(@"\\") || root.EndsWith(@"\");
}

Es ist ein bisschen einfacher als das, was bereits vorgeschlagen wurde, und es gibt immer noch false für Laufwerksrelationen wie C:foo. Seine Logik basiert direkt auf der MSDN-Definition von "voll qualifiziert", und ich habe keine Beispiele gefunden, bei denen es sich schlecht verhält.


Interessanterweise scheint .NET Core 2.1 jedoch eine neue Methode zu haben, Path.IsPathFullyQualifieddie eine interne Methode verwendet PathInternal.IsPartiallyQualified(Verbindungsposition genau ab 17.04.2018).

Für die Nachwelt und eine bessere Selbstbeherrschung dieses Beitrags ist hier die Implementierung des letzteren als Referenz:

internal static bool IsPartiallyQualified(ReadOnlySpan<char> path)
{
    if (path.Length < 2)
    {
        // It isn't fixed, it must be relative.  There is no way to specify a fixed
        // path with one character (or less).
        return true;
    }

    if (IsDirectorySeparator(path[0]))
    {
        // There is no valid way to specify a relative path with two initial slashes or
        // \? as ? isn't valid for drive relative paths and \??\ is equivalent to \\?\
        return !(path[1] == '?' || IsDirectorySeparator(path[1]));
    }

    // The only way to specify a fixed path that doesn't begin with two slashes
    // is the drive, colon, slash format- i.e. C:\
    return !((path.Length >= 3)
        && (path[1] == VolumeSeparatorChar)
        && IsDirectorySeparator(path[2])
        // To match old behavior we'll check the drive character for validity as the path is technically
        // not qualified if you don't have a valid drive. "=:\" is the "=" file's default data stream.
        && IsValidDriveChar(path[0]));
}
Wilhelm
quelle
4

Dies ist die Lösung, die ich benutze

public static bool IsFullPath(string path)
{
    try
    {
        return Path.GetFullPath(path) == path;
    }
    catch
    {
        return false;
    }
}

Es funktioniert folgendermaßen:

IsFullPath(@"c:\foo"); // true
IsFullPath(@"C:\foo"); // true
IsFullPath(@"c:\foo\"); // true
IsFullPath(@"c:/foo"); // false
IsFullPath(@"\foo"); // false
IsFullPath(@"foo"); // false
IsFullPath(@"c:1\foo\"); // false
Mykhailo Seniutovych
quelle
Sehr interessant! Es ist zum Beispiel zerbrechlich und muss mit Schrägstrichen übereinstimmen, aber das ist vielversprechend.
Nicholas Petersen
Es gibt falsche Ergebnisse für die folgenden Pfade zurück: C:\foo\..\foooderC:\foo\.\.\.
sergtk
1

Rufen Sie die folgende Funktion auf:

Path.IsPathFullyQualified(@"c:\foo")

MSDN-Dokument: Path.IsPathFullyQualified-Methode

Das nützliche Zitat aus dem MSDN-Dokument lautet:

Diese Methode behandelt Pfade, die das alternative Verzeichnistrennzeichen verwenden. Es ist ein häufiger Fehler anzunehmen, dass verwurzelte Pfade ( IsPathRooted (String) ) nicht relativ sind. Beispielsweise ist "C: a" relativ zum Laufwerk, dh es wird gegen das aktuelle Verzeichnis für C: aufgelöst (verwurzelt, aber relativ). "C: \ a" ist gerootet und nicht relativ, dh das aktuelle Verzeichnis wird nicht zum Ändern des Pfads verwendet.

sergtk
quelle
0

Ich bin mir nicht sicher, was Sie unter vollständigem Pfad verstehen (obwohl Sie aus dem Beispiel annehmen, dass Sie von der Wurzel an nicht relativ meinen). Nun, Sie können die Path- Klasse verwenden, um bei der Arbeit mit physischen Dateisystempfaden zu helfen, die abgedeckt werden sollten Sie für die meisten Eventualitäten.

Grant Thomas
quelle