web-dev-qa-db-fra.com

Vérifiez si le chemin complet est indiqué

Existe-t-il une méthode pour vérifier si le chemin donné est le chemin complet? En ce moment, je fais cela:

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

Mais il doit y avoir un moyen plus élégant de vérifier cela?

94
hs2d

Essayez d'utiliser System.IO.Path.IsPathRooted? Il renvoie également true pour les chemins absolus.

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"
128
detaylor
Path.IsPathRooted(path)
&& !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)

La condition ci-dessus:

  • ne nécessite pas d'autorisations de système de fichiers
  • renvoie false dans la plupart des cas où le format de path n'est pas valide (plutôt que de lever une exception)
  • renvoie true uniquement si path inclut le volume

Dans des scénarios comme celui que le PO a posé, il peut donc être plus approprié que les conditions des réponses précédentes. Contrairement à la condition ci-dessus:

  • path == System.IO.Path.GetFullPath(path) lève des exceptions plutôt que de renvoyer false dans ces scénarios:
    • L'appelant ne dispose pas des autorisations requises
    • Le système n'a pas pu récupérer le chemin absolu
    • chemin contient deux points (":") qui ne fait pas partie d'un identifiant de volume
    • Le chemin spécifié, le nom de fichier ou les deux dépassent la longueur maximale définie par le système
  • System.IO.Path.IsPathRooted(path) renvoie true si path commence par un seul séparateur de répertoire.

Enfin, voici une méthode qui encapsule la condition ci-dessus et exclut également les exceptions possibles restantes:

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 a fait un bon commentaire et réponse alternative adressant le cas curieux de chemins comme C: Et C:dir. Pour vous aider à décider de la manière dont vous souhaitez gérer ces chemins, vous pouvez approfondir MSDN -> Applications de bureau Windows -> Développer -> Technologies de bureau -> Accès et stockage des données -> Systèmes de fichiers locaux -> Gestion des fichiers -> À propos de la gestion des fichiers -> Création, Suppression et maintenance de fichiers -> Nommage des fichiers, des chemins et des espaces de noms -> Entièrement Chemins qualifiés contre chemins relatifs

Pour les fonctions API Windows qui manipulent les fichiers, les noms de fichiers peuvent souvent être relatifs au répertoire actuel, tandis que certaines API nécessitent un chemin d'accès complet. Un nom de fichier est relatif au répertoire actuel s'il ne commence pas par l'un des éléments suivants:

  • Un nom UNC de n'importe quel format, qui commence toujours par deux barres obliques inverses ("\"). Pour plus d'informations, consultez la section suivante.
  • Un indicateur de disque avec une barre oblique inverse, par exemple "C: \" ou "d: \".
  • Une barre oblique inverse unique, par exemple, "\ répertoire" ou "\ fichier.txt". Ceci est également appelé chemin absolu.

Si un nom de fichier commence par un seul indicateur de disque mais pas la barre oblique inverse après les deux-points, il est interprété comme un chemin d'accès relatif au répertoire en cours sur le lecteur avec la lettre spécifiée. Notez que le répertoire actuel peut être ou non le répertoire racine en fonction de ce qu'il a été défini lors de la dernière opération de "changement de répertoire" sur ce disque. Voici des exemples de ce format:

  • "C: tmp.txt" fait référence à un fichier nommé "tmp.txt" dans le répertoire en cours sur le lecteur C.
  • "C: tempdir\tmp.txt" fait référence à un fichier dans un sous-répertoire du répertoire en cours sur le lecteur C.

[...]

26
weir

Essayer

System.IO.Path.IsPathRooted(template)

Fonctionne pour les chemins UNC ainsi que les chemins locaux.

Par exemple.

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

Vieille question, mais une réponse de plus applicable. Si vous devez vous assurer que le volume est inclus dans un chemin local, vous pouvez utiliser System.IO.Path.GetFullPath () comme ceci:

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
}
12
GreggD

En s'appuyant sur la réponse de weir: cela ne lance pas pour les chemins invalides, mais renvoie également false pour les chemins comme "C:", "C: dirname" et "\ 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
}

Notez que cela renvoie des résultats différents sur Windows et Linux, par exemple "/ path" est absolu sous Linux, mais pas sous Windows.

Test de l'unité:

[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);
    }
}
9
EM0

Pour vérifier si un chemin est entièrement qualifié (MSDN) :

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

C'est un peu plus simple que ce qui a déjà été proposé, et il retourne toujours false pour les chemins relatifs au lecteur comme C:foo. Sa logique est directement basée sur la définition MSDN de "pleinement qualifié", et je n'ai trouvé aucun exemple sur lequel il se comporte mal.


Fait intéressant cependant, .NET Core 2.1 semble avoir une nouvelle méthode Path.IsPathFullyQualified qui utilise une méthode interne PathInternal.IsPartiallyQualified (emplacement du lien exact au 17/04/2018).

Pour la postérité et une meilleure maîtrise de ce post, voici l'implémentation de ce dernier pour référence:

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]));
}
4
William

C'est la solution que j'utilise

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

Cela fonctionne de la manière suivante:

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
1

Je ne suis pas vraiment sûr de ce que vous entendez par chemin complet (bien qu'en supposant dans l'exemple que vous voulez dire non relatif depuis la racine), eh bien, vous peut utiliser la classe Path pour vous aider à travailler avec les chemins physiques du système de fichiers, qui devraient vous couvrir pour la plupart des éventualités.

0
Grant Thomas