web-dev-qa-db-fra.com

En C #, vérifiez que le nom du fichier est * éventuellement * valide (pas qu'il existe)

Existe-t-il une méthode dans l'espace de noms System.IO qui vérifie la validité d'un nom de fichier?

Par exemple, C:\foo\bar validerait et :"~-* ne serait pas

Ou un peu plus délicat, X:\foo\bar validerait s'il y a un X: conduire sur le système, mais ne serait pas autrement.

Je suppose que je pourrais écrire une telle méthode moi-même, mais je suis plutôt intéressé par une méthode intégrée.

122
scru

Il suffit de faire;

System.IO.FileInfo fi = null;
try {
  fi = new System.IO.FileInfo(fileName);
}
catch (ArgumentException) { }
catch (System.IO.PathTooLongException) { }
catch (NotSupportedException) { }
if (ReferenceEquals(fi, null)) {
  // file name is not valid
} else {
  // file name is valid... May check for existence by calling fi.Exists.
}

Pour créer une instance FileInfo, le fichier n'a pas besoin d'exister.

91
mmmmmmmm

Vous pouvez obtenir une liste de caractères non valides de Path.GetInvalidPathChars et GetInvalidFileNameChars comme indiqué dans cette question.

Comme noté par jberger, il existe d'autres caractères qui ne sont pas inclus dans la réponse de cette méthode. Pour plus de détails sur la plate-forme Windows, jetez un coup d’œil à Nommer des fichiers, des chemins et des espaces de noms sur MSDN,

Comme Micah fait remarquer , il y a Directory.GetLogicalDrives pour obtenir une liste des lecteurs valides.

34
Eugene Katz

Vous pouvez utiliser la classe System.Uri. La classe Uri n'est pas seulement utile pour les URL Web, elle gère également les chemins du système de fichiers. Utilisez la méthode Uri.TryCreate pour rechercher si le chemin est racine, puis utilisez la propriété IsLoopback pour déterminer si Uri fait référence à la machine locale.

Voici une méthode simple permettant de déterminer si une chaîne est un chemin de fichier valide, local et enraciné.

public bool IsPathValidRootedLocal(String pathString) {
    Uri pathUri;
    Boolean isValidUri = Uri.TryCreate(pathString, UriKind.Absolute, out pathUri);
    return isValidUri && pathUri != null && pathUri.IsLoopback;
}

Je suis convaincu que cela fonctionnera.

11
LamdaComplex

Vous pouvez utiliser plusieurs méthodes qui existent dans le System.IO espace de noms:

Directory.GetLogicalDrives() // Returns an array of strings like "c:\"
Path.GetInvalidFileNameChars() // Returns an array of characters that cannot be used in a file name
Path.GetInvalidPathChars() // Returns an array of characters that cannot be used in a path.

Comme suggéré, vous pouvez alors faire ceci:

bool IsValidFilename(string testName) {
    string regexString = "[" + Regex.Escape(Path.GetInvalidPathChars()) + "]";
    Regex containsABadCharacter = new Regex(regexString);
    if (containsABadCharacter.IsMatch(testName)) {
        return false;
    }

    // Check for drive
    string pathRoot = Path.GetPathRoot(testName);
    if (Directory.GetLogicalDrives().Contains(pathRoot)) {
        // etc
    }

    // other checks for UNC, drive-path format, etc

    return true;
}
9
Micah

Je pensais publier une solution à partir de réponses trouvées après avoir cherché une solution robuste au même problème. Espérons que cela aide quelqu'un d'autre.

using System;
using System.IO;
//..

public static bool ValidateFilePath(string path, bool RequireDirectory, bool IncludeFileName, bool RequireFileName = false)
{
    if (string.IsNullOrEmpty(path)) { return false; }
    string root = null;
    string directory = null;
    string filename = null;
    try
    {
        // throw ArgumentException - The path parameter contains invalid characters, is empty, or contains only white spaces.
        root = Path.GetPathRoot(path);

        // throw ArgumentException - path contains one or more of the invalid characters defined in GetInvalidPathChars.
        // -or- String.Empty was passed to path.
        directory = Path.GetDirectoryName(path);

        // path contains one or more of the invalid characters defined in GetInvalidPathChars
        if (IncludeFileName) { filename = Path.GetFileName(path); }
    }
    catch (ArgumentException)
    {
        return false;
    }

    // null if path is null, or an empty string if path does not contain root directory information
    if (String.IsNullOrEmpty(root)) { return false; }

    // null if path denotes a root directory or is null. Returns String.Empty if path does not contain directory information
    if (String.IsNullOrEmpty(directory)) { return false; }

    if (RequireFileName)
    {
        // if the last character of path is a directory or volume separator character, this method returns String.Empty
        if (String.IsNullOrEmpty(filename)) { return false; }

        // check for illegal chars in filename
        if (filename.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0) { return false; }
    }
    return true;
}
5
Enisle

Même si le nom de fichier est valide, vous souhaiterez peut-être toujours utiliser touch pour vous assurer que l'utilisateur est autorisé à écrire.

Si vous ne voulez pas créer des centaines de fichiers sur le disque dans un court laps de temps, je pense que la création d'un fichier vide est une approche raisonnable.

Si vous voulez vraiment quelque chose de plus léger, comme vérifier uniquement les caractères non valides, comparez votre nom de fichier à Path.GetInvalidFileNameChars ().

5
Michael Haren

Essayez cette méthode qui tenterait de couvrir tous les scénarios possibles d’exceptions. Cela fonctionnerait pour presque tous les chemins associés à Windows.

/// <summary>
/// Validate the Path. If path is relative append the path to the project directory by default.
/// </summary>
/// <param name="path">Path to validate</param>
/// <param name="RelativePath">Relative path</param>
/// <param name="Extension">If want to check for File Path</param>
/// <returns></returns>
private static bool ValidateDllPath(ref string path, string RelativePath = "", string Extension = "") {
    // Check if it contains any Invalid Characters.
    if (path.IndexOfAny(Path.GetInvalidPathChars()) == -1) {
        try {
            // If path is relative take %IGXLROOT% as the base directory
            if (!Path.IsPathRooted(path)) {
                if (string.IsNullOrEmpty(RelativePath)) {
                    // Exceptions handled by Path.GetFullPath
                    // ArgumentException path is a zero-length string, contains only white space, or contains one or more of the invalid characters defined in GetInvalidPathChars. -or- The system could not retrieve the absolute path.
                    // 
                    // SecurityException The caller does not have the required permissions.
                    // 
                    // ArgumentNullException path is null.
                    // 
                    // NotSupportedException path contains a colon (":") that is not part of a volume identifier (for example, "c:\"). 
                    // PathTooLongException The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.

                    // RelativePath is not passed so we would take the project path 
                    path = Path.GetFullPath(RelativePath);

                } else {
                    // Make sure the path is relative to the RelativePath and not our project directory
                    path = Path.Combine(RelativePath, path);
                }
            }

            // Exceptions from FileInfo Constructor:
            //   System.ArgumentNullException:
            //     fileName is null.
            //
            //   System.Security.SecurityException:
            //     The caller does not have the required permission.
            //
            //   System.ArgumentException:
            //     The file name is empty, contains only white spaces, or contains invalid characters.
            //
            //   System.IO.PathTooLongException:
            //     The specified path, file name, or both exceed the system-defined maximum
            //     length. For example, on Windows-based platforms, paths must be less than
            //     248 characters, and file names must be less than 260 characters.
            //
            //   System.NotSupportedException:
            //     fileName contains a colon (:) in the middle of the string.
            FileInfo fileInfo = new FileInfo(path);

            // Exceptions using FileInfo.Length:
            //   System.IO.IOException:
            //     System.IO.FileSystemInfo.Refresh() cannot update the state of the file or
            //     directory.
            //
            //   System.IO.FileNotFoundException:
            //     The file does not exist.-or- The Length property is called for a directory.
            bool throwEx = fileInfo.Length == -1;

            // Exceptions using FileInfo.IsReadOnly:
            //   System.UnauthorizedAccessException:
            //     Access to fileName is denied.
            //     The file described by the current System.IO.FileInfo object is read-only.-or-
            //     This operation is not supported on the current platform.-or- The caller does
            //     not have the required permission.
            throwEx = fileInfo.IsReadOnly;

            if (!string.IsNullOrEmpty(Extension)) {
                // Validate the Extension of the file.
                if (Path.GetExtension(path).Equals(Extension, StringComparison.InvariantCultureIgnoreCase)) {
                    // Trim the Library Path
                    path = path.Trim();
                    return true;
                } else {
                    return false;
                }
            } else {
                return true;

            }
        } catch (ArgumentNullException) {
            //   System.ArgumentNullException:
            //     fileName is null.
        } catch (System.Security.SecurityException) {
            //   System.Security.SecurityException:
            //     The caller does not have the required permission.
        } catch (ArgumentException) {
            //   System.ArgumentException:
            //     The file name is empty, contains only white spaces, or contains invalid characters.
        } catch (UnauthorizedAccessException) {
            //   System.UnauthorizedAccessException:
            //     Access to fileName is denied.
        } catch (PathTooLongException) {
            //   System.IO.PathTooLongException:
            //     The specified path, file name, or both exceed the system-defined maximum
            //     length. For example, on Windows-based platforms, paths must be less than
            //     248 characters, and file names must be less than 260 characters.
        } catch (NotSupportedException) {
            //   System.NotSupportedException:
            //     fileName contains a colon (:) in the middle of the string.
        } catch (FileNotFoundException) {
            // System.FileNotFoundException
            //  The exception that is thrown when an attempt to access a file that does not
            //  exist on disk fails.
        } catch (IOException) {
            //   System.IO.IOException:
            //     An I/O error occurred while opening the file.
        } catch (Exception) {
            // Unknown Exception. Might be due to wrong case or nulll checks.
        }
    } else {
        // Path contains invalid characters
    }
    return false;
}
2
vCillusion

Utilisez la méthode statique GetInvalidFileNameChars sur le Path class dans le System.IO namespace pour déterminer quels caractères sont illégaux dans un nom de fichier.

Pour ce faire dans un chemin, appelez la méthode statique GetInvalidPathChars de la même classe.

Pour déterminer si la racine d'un chemin est valide, appelez la méthode static GetPathRoot de la classe Path. pour obtenir la racine, utilisez ensuite la Directory class pour déterminer s’il est valide. Ensuite, vous pouvez valider le reste du chemin normalement.

2
casperOne

Plusieurs méthodes System.IO.Path lèveront des exceptions si le chemin ou le nom du fichier n'est pas valide:

  • Path.IsPathRooted ()
  • Path.GetFileName ()

http://msdn.Microsoft.com/en-us/library/system.io.path_methods.aspx

2
shackett

J'ai eu de la chance en utilisant des expressions régulières comme d'autres l'ont montré.

Une chose à garder à l'esprit est que Windows interdit au moins certains noms de fichiers contenant par ailleurs des caractères légaux. Quelques-uns me viennent à l'esprit: com, nul, prn.

Je ne l'ai pas avec moi maintenant, mais j'ai un regex qui prend en compte ces noms de fichiers. Si vous voulez, je peux le poster, sinon je suis sûr que vous pourrez le trouver de la même façon que je l'ai fait: Google.

-Geai

1
Jay Riggs

Je ne connais rien qui puisse valider tout cela pour vous, cependant la classe Path dans .NET peut vous aider énormément.

Pour commencer, il a:

char[] invalidChars = Path.GetInvalidFileNameChars(); //returns invalid charachters

ou:

Path.GetPathRoot(string); // will return the root.
1
BFree

Cela vous donnera les lecteurs sur la machine:

System.IO.DriveInfo.GetDrives()

Ces deux méthodes vous permettront de vérifier les mauvais caractères:

System.IO.Path.GetInvalidFileNameChars();
System.IO.Path.GetInvalidPathChars();
0
Austin Salonen

Pensez qu'il est trop tard pour répondre, mais ... :) en cas de chemin d'accès avec le nom du volume, vous pouvez écrire quelque chose comme ceci:

using System;
using System.Linq;
using System.IO;

// ...

var drives = Environment.GetLogicalDrives();
var invalidChars = Regex.Replace(new string(Path.GetInvalidFileNameChars()), "[\\\\/]", "");
var drive = drives.FirstOrDefault(d => filePath.StartsWith(d));
if (drive != null) {
    var fileDirPath = filePath.Substring(drive.Length);
    if (0 < fileDirPath.Length) {
        if (fileDirPath.IndexOfAny(invalidChars.ToCharArray()) == -1) {
            if (Path.Combine(drive, fileDirPath) != drive) {
                // path correct and we can proceed
            }
        }
    }
}
0
QgecNick

Le meilleur moyen est probablement de créer une méthode personnalisée combinant une combinaison de regex et de petites recherches sur votre système de fichiers (pour voir les lecteurs, par exemple).

0
tanathos