55 votes

Valider le nom d'un fichier sous Windows

public static boolean isValidName(String text)
{
    Pattern pattern = Pattern.compile("^[^/./\\:*?\"<>|]+$");
    Matcher matcher = pattern.matcher(text);
    boolean isMatch = matcher.matches();
    return isMatch;
}

Cette méthode garantit-elle un nom de fichier valide sous Windows ?

89voto

ridgerunner Points 14773

Compte tenu des exigences spécifiées dans le document documentation MSDN citée la regex suivante devrait faire l'affaire :

public static boolean isValidName(String text)
{
    Pattern pattern = Pattern.compile(
        "# Match a valid Windows filename (unspecified file system).          \n" +
        "^                                # Anchor to start of string.        \n" +
        "(?!                              # Assert filename is not: CON, PRN, \n" +
        "  (?:                            # AUX, NUL, COM1, COM2, COM3, COM4, \n" +
        "    CON|PRN|AUX|NUL|             # COM5, COM6, COM7, COM8, COM9,     \n" +
        "    COM[1-9]|LPT[1-9]            # LPT1, LPT2, LPT3, LPT4, LPT5,     \n" +
        "  )                              # LPT6, LPT7, LPT8, and LPT9...     \n" +
        "  (?:\\.[^.]*)?                  # followed by optional extension    \n" +
        "  $                              # and end of string                 \n" +
        ")                                # End negative lookahead assertion. \n" +
        "[^<>:\"/\\\\|?*\\x00-\\x1F]*     # Zero or more valid filename chars.\n" +
        "[^<>:\"/\\\\|?*\\x00-\\x1F\\ .]  # Last char is not a space or dot.  \n" +
        "$                                # Anchor to end of string.            ", 
        Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE | Pattern.COMMENTS);
    Matcher matcher = pattern.matcher(text);
    boolean isMatch = matcher.matches();
    return isMatch;
}

Notez que cette regex n'impose aucune limite à la longueur du nom de fichier, mais un nom de fichier réel peut être limité à 260 ou 32767 caractères selon la plate-forme.

26voto

Monday Points 949

De plus, sous Windows et DOS, certains mots peuvent également être réservés et ne peuvent pas être utilisés comme noms de fichiers.

CON, PRN, AUX, CLOCK$, NUL
COM0, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9
LPT0, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9.

Voir

http://en.wikipedia.org/wiki/Filename


Editer:

Windows limite généralement les noms de fichiers à 260 caractères. Mais le nom du fichier doit en fait être plus court que cela, puisque le chemin complet (tel que C:\Program Fichiers \filename.txt ) est inclus dans ce nombre de caractères.

C'est pourquoi vous pouvez parfois rencontrer une erreur lorsque vous copiez un fichier dont le nom est très long vers un emplacement dont le chemin est plus long que son emplacement actuel.

16voto

Eng.Fouad Points 44085

Eh bien, je pense que la méthode suivante garantirait un nom de fichier valide :

public static boolean isValidName(String text)
{
    try
    {
        File file = new File(text);
        file.createNewFile();
        if(file.exists()) file.delete();
        return true;
    }
    catch(Exception ex){}
    return false;
}

Qu'en pensez-vous ?

13voto

drf Points 4318

Une méthode qui garantirait, de manière générale, qu'un nom de fichier Windows est valide -- qu'il serait légal de créer un fichier de ce nom -- serait impossible à mettre en œuvre.

Il est relativement simple de garantir qu'un nom de fichier Windows est invalide . Certaines des autres regex tentent de le faire. Cependant, la question originale demande une affirmation plus forte : une méthode qui garanties le nom du fichier est valide sous Windows.

El Référence MSDN cité dans d'autres réponses indique qu'un nom de fichier Windows ne peut pas contenir "Tout autre caractère que le système de fichiers cible n'autorise pas". Par exemple, un fichier contenant NUL serait invalide sur certains systèmes de fichiers, tout comme les caractères Unicode étendus sur certains systèmes de fichiers plus anciens. Ainsi, un fichier appelé ☃.txt serait valide dans certains cas, mais pas dans d'autres. Ainsi, qu'un hypothétique isValidName(\"☃\") retournerait vrai dépend du système de fichiers sous-jacent.

Supposons toutefois qu'une telle fonction soit conservatrice et exige que le nom du fichier soit composé de caractères ASCII imprimables. Toutes les versions modernes de Windows prennent en charge de manière native les formats de fichiers NTFS, FAT32 et FAT16, qui acceptent les noms de fichiers Unicode. Mais il est possible d'installer des pilotes pour des systèmes de fichiers arbitraires, et on est libre de créer un système de fichiers qui n'autorise pas, par exemple, la lettre 'n'. Ainsi, on ne peut même pas "garantir" la validité d'un simple fichier comme "snowman.txt".

Mais même en mettant de côté les cas extrêmes, il existe d'autres complications. Par exemple, un fichier nommé "$LogFile" ne peut pas exister dans le répertoire racine d'un volume NTFS, mais peut exister ailleurs sur le volume. Ainsi, sans connaître le répertoire, nous ne pouvons pas savoir si "$LogFile" est un nom valide. Mais même " C:\data\ $LogFile" pourrait être invalide si, par exemple, "c : \data\ " est un lien symbolique vers un autre volume NTFS Root. (De même, "D:\$LogFile" peut être valide si D : est un alias vers un sous-répertoire d'un volume NTFS).

Il y a encore plus de complications. Les flux de données alternatifs sur les fichiers, par exemple, sont légaux sur les volumes NTFS, de sorte que "snowman.txt:☃" peut être valide. Les trois principaux systèmes de fichiers de Windows ont tous des restructions de la longueur du chemin, de sorte que la validité du nom de fichier est également fonction du chemin. Mais la longueur du chemin physique peut ne pas être disponible pour le système de fichiers. isValidName si le chemin est un alias virtuel, un lecteur réseau mappé ou un lien symbolique plutôt qu'un chemin physique sur le volume.

D'autres ont proposé une autre solution : créer un fichier portant le nom proposé, puis le supprimer, en renvoyant true si et seulement si la création réussit. Cette approche présente plusieurs problèmes pratiques et théoriques. L'un d'eux, comme indiqué précédemment, est que la validité est une fonction à la fois du nom de fichier et du chemin, donc la validité de c : \test\ ☃.txt pourrait différer de la validité de c : \test2\ ☃.txt. De plus, la fonction échouerait à écrire le fichier pour un nombre quelconque de raisons non liées à la validité du fichier, comme le fait de ne pas avoir les droits d'écriture sur le répertoire. Un troisième défaut est que la validité d'un nom de fichier n'a pas besoin d'être non-déterministe : un système de fichiers hypothétique pourrait, par exemple, ne pas permettre à un fichier supprimé d'être remplacé, ou (en théorie) pourrait même décider aléatoirement si un nom de fichier est valide.

En guise d'alternative, il est assez simple de créer une méthode isInvalidFileName(String text) qui renvoie vrai si le fichier est garanti no sont valides sous Windows ; les noms de fichiers tels que "aux", "*" et "abc.txt." renvoient la réponse vraie. L'opération de création de fichier vérifierait d'abord que le nom de fichier est garanti comme étant invalide et, si elle renvoie faux, s'arrêterait. Sinon, la méthode pourrait tenter de créer le fichier, tout en étant préparée au cas limite où le fichier ne peut pas être créé parce que le nom de fichier est invalide.

9voto

Xeno Points 826

Je poste une nouvelle réponse car je n'ai pas le seuil de rep pour commenter le code de Eng.Fouad.

public static boolean isValidName(String text)
{
    try
    {
        File file = new File(text);
        if(file.createNewFile()) file.delete();
        return true;
    }
    catch(Exception ex){}
    return false;
}

Une petite modification de votre réponse qui empêche la suppression d'un fichier préexistant. Les fichiers ne sont supprimés que s'ils ont été créés lors de cet appel de méthode, la valeur de retour restant la même.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X