Je souhaite inclure une fonctionnalité de changement de nom de fichier de commandes dans mon application. Un utilisateur peut taper un modèle de nom de fichier de destination et (après avoir remplacé certains caractères génériques dans le modèle), je dois vérifier si ce sera un nom de fichier légal sous Windows. J'ai essayé d'utiliser des expressions régulières comme [a-zA-Z0-9_]+
mais cela n'inclut pas beaucoup de caractères nationaux spécifiques de différentes langues (par exemple, des trémas, etc.). Quelle est la meilleure façon de procéder à une telle vérification?
c#
windows
file
filesystems
Tomash
la source
la source
Réponses:
Vous pouvez obtenir une liste de caractères non valides à partir de
Path.GetInvalidPathChars
etGetInvalidFileNameChars
.UPD: Voir la suggestion de Steve Cooper sur la façon de les utiliser dans une expression régulière.
UPD2: Notez que selon la section Remarques dans MSDN "Le tableau renvoyé par cette méthode n'est pas garanti pour contenir le jeu complet de caractères qui ne sont pas valides dans les noms de fichiers et de répertoires." La réponse fournie par sixlettervaliables entre dans plus de détails.
la source
À partir de «Nommer un fichier ou un répertoire» de MSDN, voici les conventions générales pour définir ce qu'est un nom de fichier légal sous Windows:
Vous pouvez utiliser n'importe quel caractère de la page de codes actuelle (Unicode / ANSI supérieur à 127), sauf:
<
>
:
"
/
\
|
?
*
Quelques éléments facultatifs à vérifier:
\?\
préfixe)\?\
(notez que le préfixe peut développer les composants du répertoire et provoquer le dépassement de la limite de 32 000)la source
Regex unspupportedRegex = new Regex("(^(PRN|AUX|NUL|CON|COM[1-9]|LPT[1-9]|(\\.+)$)(\\..*)?$)|(([\\x00-\\x1f\\\\?*:\";|/<>])+)|(([\\. ]+)", RegexOptions.IgnoreCase);
^(?!^(?:PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d)(?:\..+)?$)(?:\.*?(?!\.))[^\x00-\x1f\\?*:\";|\/<>]+(?<![\s.])$
Pour les frameworks .Net antérieurs à la version 3.5, cela devrait fonctionner:
La correspondance d'expressions régulières devrait vous aider. Voici un extrait de code utilisant la
System.IO.Path.InvalidPathChars
constante;Pour .Net Frameworks après 3.0, cela devrait fonctionner:
http://msdn.microsoft.com/en-us/library/system.io.path.getinvalidpathchars(v=vs.90).aspx
La correspondance d'expressions régulières devrait vous aider. Voici un extrait de code utilisant la
System.IO.Path.GetInvalidPathChars()
constante;Une fois que vous savez cela, vous devriez également vérifier les différents formats, par exemple
c:\my\drive
et\\server\share\dir\file.ext
la source
Essayez de l'utiliser et piègez l'erreur. L'ensemble autorisé peut changer entre les systèmes de fichiers ou entre les différentes versions de Windows. En d'autres termes, si vous voulez savoir si Windows aime le nom, donnez-lui le nom et laissez-le vous dire.
la source
Cette classe nettoie les noms de fichiers et les chemins; utilisez-le comme
Voici le code;
la source
Voici ce que j'utilise:
Le premier modèle crée une expression régulière contenant les noms de fichiers et les caractères non valides / illégaux pour les plates-formes Windows uniquement. Le second fait de même mais garantit que le nom est légal pour n'importe quelle plateforme.
la source
@"^(?!(?:PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d)(?:\..+)?$)[^\x00-\x1F\xA5\\?*:\"";|\/<>]+(?<![\s.])$"
Un cas d'angle à garder à l'esprit, ce qui m'a surpris lorsque j'ai découvert cela pour la première fois: Windows autorise les caractères d'espace de début dans les noms de fichiers! Par exemple, les noms de fichiers suivants sont tous légaux et distincts sous Windows (moins les guillemets):
Une chose à retenir: soyez prudent lorsque vous écrivez du code qui supprime les espaces de début / de fin d'une chaîne de nom de fichier.
la source
Simplifier la réponse d'Eugene Katz:
Ou
la source
Path.GetInvalidFileNameChars
. Jetez un œil ici: referencesource.microsoft.com/#mscorlib/system/io/path.cs,289 - pour chaque caractère de votrefileName
, un clone du tableau est créé.Microsoft Windows: le noyau Windows interdit l'utilisation de caractères compris entre 1 et 31 (c'est-à-dire 0x01-0x1F) et les caractères "*: <>? \ |. Bien que NTFS autorise chaque composant de chemin (répertoire ou nom de fichier) à 255 caractères et jusqu'à environ 32 767 caractères, le noyau Windows ne prend en charge que les chemins jusqu'à 259 caractères. De plus, Windows interdit l'utilisation des noms de périphérique MS-DOS AUX, CLOCK $, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, CON, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9, NUL et PRN, ainsi que ces noms avec n'importe quelle extension (par exemple, AUX.txt), sauf lors de l'utilisation Chemins UNC longs (ex. \. \ C: \ nul.txt ou \? \ D: \ aux \ con). (En fait, CLOCK $ peut être utilisé si une extension est fournie.) Ces restrictions s'appliquent uniquement à Windows - Linux, par exemple, autorise l'utilisation de "*: <>? \ | même en NTFS.
Source: http://en.wikipedia.org/wiki/Filename
la source
Plutôt que d'inclure explicitement tous les caractères possibles, vous pouvez faire une regex pour vérifier la présence de caractères illégaux et signaler une erreur ensuite. Idéalement, votre application doit nommer les fichiers exactement comme l'utilisateur le souhaite, et ne crier au scandale que si elle tombe sur une erreur.
la source
La question est de savoir si vous essayez de déterminer si un nom de chemin est un chemin Windows légal ou s'il est légal sur le système sur lequel le code est exécuté. ? Je pense que ce dernier est plus important, donc personnellement, je décomposerais probablement le chemin complet et essayerais d'utiliser _mkdir pour créer le répertoire auquel appartient le fichier, puis essayer de créer le fichier.
De cette façon, vous savez non seulement si le chemin contient uniquement des caractères Windows valides, mais s'il représente en fait un chemin qui peut être écrit par ce processus.
la source
J'utilise ceci pour me débarrasser des caractères invalides dans les noms de fichiers sans lever d'exceptions:
la source
De plus, CON, PRN, AUX, NUL, COM # et quelques autres ne sont jamais des noms de fichiers légaux dans aucun répertoire avec une extension.
la source
Pour compléter les autres réponses, voici quelques cas supplémentaires que vous voudrez peut-être envisager.
Excel peut rencontrer des problèmes si vous enregistrez un classeur dans un fichier dont le nom contient les caractères «[» ou «]». Voir http://support.microsoft.com/kb/215205 pour plus de détails.
Sharepoint a tout un ensemble de restrictions supplémentaires. Voir http://support.microsoft.com/kb/905231 pour plus de détails.
la source
Depuis MSDN , voici une liste de caractères non autorisés:
la source
Le système de fichiers de destination est également important.
Sous NTFS, certains fichiers ne peuvent pas être créés dans des répertoires spécifiques. EG $ Boot en root
la source
$Boot
existe déjà dans le répertoire?C'est une question déjà répondue, mais juste pour le plaisir des "Autres options", en voici une non idéale:
(non idéal car l'utilisation d'exceptions comme contrôle de flux est généralement une mauvaise chose)
la source
true
.Les expressions régulières sont excessives pour cette situation. Vous pouvez utiliser la
String.IndexOfAny()
méthode en combinaison avecPath.GetInvalidPathChars()
etPath.GetInvalidFileNameChars()
.Notez également que les deux
Path.GetInvalidXXX()
méthodes clonent un tableau interne et renvoient le clone. Donc, si vous comptez faire cela beaucoup (des milliers et des milliers de fois), vous pouvez mettre en cache une copie du tableau de caractères invalides pour une réutilisation.la source
Si vous essayez seulement de vérifier si une chaîne contenant votre nom / chemin de fichier contient des caractères non valides, la méthode la plus rapide que j'ai trouvée consiste
Split()
à diviser le nom de fichier en un tableau de parties partout où il y a un caractère non valide. Si le résultat n'est qu'un tableau de 1, il n'y a pas de caractères non valides. :-)J'ai essayé d'exécuter cette méthode et d'autres méthodes mentionnées ci-dessus sur un nom de fichier / chemin 1 000 000 fois dans LinqPad.
L'utilisation
Split()
ne dure que ~ 850 ms.L'utilisation
Regex("[" + Regex.Escape(new string(System.IO.Path.GetInvalidPathChars())) + "]")
est d'environ 6 secondes.Les expressions régulières les plus compliquées sont bien pires, tout comme certaines des autres options, comme l'utilisation des différentes méthodes de la
Path
classe pour obtenir le nom de fichier et laisser leur validation interne faire le travail (probablement en raison de la surcharge de la gestion des exceptions).Certes, il n'est pas très souvent nécessaire de valider 1 million de noms de fichiers, donc une seule itération convient de toute façon pour la plupart de ces méthodes. Mais c'est toujours assez efficace et efficace si vous ne recherchez que des caractères invalides.
la source
beaucoup de ces réponses ne fonctionneront pas si le nom de fichier est trop long et s'exécute dans un environnement antérieur à Windows 10. De même, pensez à ce que vous voulez faire avec les points - autoriser le début ou la fin est techniquement valide, mais peut créer des problèmes si vous ne voulez pas que le fichier soit difficile à voir ou à supprimer respectivement.
C'est un attribut de validation que j'ai créé pour vérifier un nom de fichier valide.
et les tests
la source
Ma tentative:
Ce n'est pas parfait car
Path.GetInvalidPathChars
ne renvoie pas le jeu complet de caractères invalides dans les noms de fichiers et de répertoires et bien sûr, il y a beaucoup plus de subtilités.J'utilise donc cette méthode en complément:
Il essaie de créer le fichier et renvoie false s'il y a une exception. Bien sûr, je dois créer le fichier, mais je pense que c'est le moyen le plus sûr de le faire. Veuillez également noter que je ne supprime pas les répertoires qui ont été créés.
Vous pouvez également utiliser la première méthode pour effectuer une validation de base, puis gérer soigneusement les exceptions lorsque le chemin est utilisé.
la source
Je suggère simplement d'utiliser le Path.GetFullPath ()
la source
J'ai eu cette idée de quelqu'un. - ne sais pas qui. Laissez le système d'exploitation faire le gros du travail.
la source
Cette vérification
filtre les noms avec les caractères non valides (
<>:"/\|?*
et ASCII 0-31), ainsi que des dispositifs DOS réservés (CON
,NUL
,COMx
). Il permet des espaces de début et des noms de points, cohérents avecPath.GetFullPath
. (La création d'un fichier avec des espaces de début réussit sur mon système).Utilisé .NET Framework 4.7.1, testé sur Windows 7.
la source
Une doublure pour vérifier les caractères illigaux dans la chaîne:
la source
À mon avis, la seule réponse appropriée à cette question est d'essayer d'utiliser le chemin et de laisser le système d'exploitation et le système de fichiers le valider. Sinon, vous ne faites que réimplémenter (et probablement mal) toutes les règles de validation que le système d'exploitation et le système de fichiers utilisent déjà et si ces règles sont modifiées à l'avenir, vous devrez modifier votre code pour les faire correspondre.
la source
Windows sont assez les noms de fichiers non restrictive, si vraiment il pourrait même ne pas être que beaucoup d'une question. Les caractères non autorisés par Windows sont:
Vous pouvez facilement écrire une expression pour vérifier si ces caractères sont présents. Une meilleure solution serait cependant d'essayer de nommer les fichiers comme l'utilisateur le souhaite et de les alerter lorsqu'un nom de fichier ne colle pas.
la source