Ich möchte eine Funktion zum Umbenennen von Batchdateien in meine Anwendung aufnehmen. Ein Benutzer kann ein Zieldateinamenmuster eingeben und (nachdem er einige Platzhalter im Muster ersetzt hat) muss ich überprüfen, ob es sich unter Windows um einen legalen Dateinamen handelt. Ich habe versucht, reguläre Ausdrücke wie zu verwenden, [a-zA-Z0-9_]+
aber es enthält nicht viele nationalspezifische Zeichen aus verschiedenen Sprachen (z. B. Umlaute usw.). Was ist der beste Weg, um eine solche Überprüfung durchzuführen?
c#
windows
file
filesystems
Tomash
quelle
quelle
Antworten:
Sie können eine Liste ungültiger Zeichen von
Path.GetInvalidPathChars
und erhaltenGetInvalidFileNameChars
.UPD: Siehe Steve Coopers Vorschlag, wie man diese in einem regulären Ausdruck verwendet.
UPD2: Beachten Sie, dass gemäß dem Abschnitt "Bemerkungen" in MSDN "das von dieser Methode zurückgegebene Array nicht garantiert den vollständigen Satz von Zeichen enthält, die in Datei- und Verzeichnisnamen ungültig sind." Die Antwort von sixlettervaliables geht auf weitere Details ein.
quelle
In MSDNs "Benennen einer Datei oder eines Verzeichnisses" finden Sie hier die allgemeinen Konventionen für die Verwendung eines legalen Dateinamens unter Windows:
Sie können ein beliebiges Zeichen in der aktuellen Codepage verwenden (Unicode / ANSI über 127), außer:
<
>
:
"
/
\
|
?
*
Einige optionale Dinge zu überprüfen:
\?\
Präfix nicht verwenden ).\?\
(beachten Sie, dass das Präfix Verzeichniskomponenten erweitern und dazu führen kann, dass das Limit von 32.000 überschritten wird)quelle
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.])$
Für .Net Frameworks vor 3.5 sollte dies funktionieren:
Der Abgleich regulärer Ausdrücke sollte Ihnen einen Teil des Weges erleichtern. Hier ist ein Ausschnitt mit dem
System.IO.Path.InvalidPathChars
Konstante.Zum .Net Frameworks nach 3.0 sollte dies funktionieren:
http://msdn.microsoft.com/en-us/library/system.io.path.getinvalidpathchars(v=vs.90).aspx
Der Abgleich regulärer Ausdrücke sollte Ihnen einen Teil des Weges erleichtern. Hier ist ein Ausschnitt mit der
System.IO.Path.GetInvalidPathChars()
Konstante.Sobald Sie das wissen, sollten Sie auch nach verschiedenen Formaten suchen, z. B.
c:\my\drive
und\\server\share\dir\file.ext
quelle
Versuchen Sie es zu verwenden und suchen Sie nach dem Fehler. Der zulässige Satz kann sich zwischen Dateisystemen oder zwischen verschiedenen Windows-Versionen ändern. Mit anderen Worten, wenn Sie wissen möchten, ob Windows den Namen mag, geben Sie ihm den Namen und lassen Sie sich davon erzählen.
quelle
Diese Klasse bereinigt Dateinamen und Pfade. benutze es wie
Hier ist der Code;
quelle
Das benutze ich:
Das erste Muster erstellt einen regulären Ausdruck, der die ungültigen / unzulässigen Dateinamen und Zeichen nur für Windows-Plattformen enthält. Der zweite macht dasselbe, stellt jedoch sicher, dass der Name für jede Plattform legal ist.
quelle
@"^(?!(?:PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d)(?:\..+)?$)[^\x00-\x1F\xA5\\?*:\"";|\/<>]+(?<![\s.])$"
Ein Eckfall, den ich beachten sollte, der mich überraschte, als ich zum ersten Mal davon erfuhr: Windows erlaubt führende Leerzeichen in Dateinamen! Zum Beispiel sind die folgenden alle legalen und unterschiedlichen Dateinamen unter Windows (abzüglich der Anführungszeichen):
Eine Erkenntnis daraus: Seien Sie vorsichtig, wenn Sie Code schreiben, der führende / nachfolgende Leerzeichen von einer Dateinamenzeichenfolge trimmt.
quelle
Vereinfachung der Antwort von Eugene Katz:
Oder
quelle
Path.GetInvalidFileNameChars
. Schauen Sie hier nach: referencesource.microsoft.com/#mscorlib/system/io/path.cs,289 - für jedes Zeichen von IhnenfileName
wird ein Klon des Arrays erstellt.Microsoft Windows: Der Windows-Kernel verbietet die Verwendung von Zeichen im Bereich 1-31 (dh 0x01-0x1F) und Zeichen "*: <>? \ |. Obwohl NTFS zulässt, dass jede Pfadkomponente (Verzeichnis oder Dateiname) 255 Zeichen lang und länger ist Pfade mit einer Länge von bis zu 32767 Zeichen, der Windows-Kernel unterstützt nur Pfade mit einer Länge von bis zu 259 Zeichen. Außerdem verbietet Windows die Verwendung der MS-DOS-Gerätenamen AUX, CLOCK $, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, CON, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9, NUL und PRN sowie diese Namen mit einer beliebigen Erweiterung (z. B. AUX.txt), außer bei Verwendung Lange UNC-Pfade (z. B. \. \ C: \ nul.txt oder \? \ D: \ aux \ con). (Tatsächlich kann CLOCK $ verwendet werden, wenn eine Erweiterung bereitgestellt wird.) Diese Einschränkungen gelten nur für Windows - Linux erlaubt zum Beispiel die Verwendung von "*: <>? \ | sogar in NTFS.
Quelle: http://en.wikipedia.org/wiki/Filename
quelle
Anstatt alle möglichen Zeichen explizit einzuschließen, können Sie eine Regex durchführen, um das Vorhandensein unzulässiger Zeichen zu überprüfen und dann einen Fehler zu melden. Im Idealfall sollte Ihre Anwendung die Dateien genau so benennen, wie es der Benutzer wünscht, und nur dann schlecht weinen, wenn ein Fehler auftritt.
quelle
Die Frage ist, ob Sie versuchen festzustellen, ob ein Pfadname ein zulässiger Windows-Pfad ist oder ob er auf dem System, auf dem der Code ausgeführt wird, zulässig ist.? Ich denke, letzteres ist wichtiger, also würde ich persönlich wahrscheinlich den vollständigen Pfad zerlegen und versuchen, mit _mkdir das Verzeichnis zu erstellen, in das die Datei gehört, und dann versuchen, die Datei zu erstellen.
Auf diese Weise wissen Sie nicht nur, ob der Pfad nur gültige Windows-Zeichen enthält, sondern auch, ob er tatsächlich einen Pfad darstellt, der von diesem Prozess geschrieben werden kann.
quelle
Ich benutze dies, um ungültige Zeichen in Dateinamen zu entfernen, ohne Ausnahmen auszulösen:
quelle
Auch CON, PRN, AUX, NUL, COM # und einige andere sind niemals legale Dateinamen in einem Verzeichnis mit einer Erweiterung.
quelle
Um die anderen Antworten zu ergänzen, finden Sie hier einige zusätzliche Randfälle, die Sie möglicherweise berücksichtigen möchten.
Excel kann Probleme haben, wenn Sie eine Arbeitsmappe in einer Datei speichern, deren Name die Zeichen '[' oder ']' enthält. Weitere Informationen finden Sie unter http://support.microsoft.com/kb/215205 .
Sharepoint unterliegt einer Reihe zusätzlicher Einschränkungen. Weitere Informationen finden Sie unter http://support.microsoft.com/kb/905231 .
quelle
In MSDN finden Sie eine Liste von Zeichen, die nicht zulässig sind:
quelle
Auch das Zieldateisystem ist wichtig.
Unter NTFS können einige Dateien nicht in bestimmten Verzeichnissen erstellt werden. EG $ Boot in root
quelle
$Boot
bereits im Verzeichnis vorhanden ist?Dies ist eine bereits beantwortete Frage, aber nur aus Gründen der "anderen Optionen" ist hier eine nicht ideale:
(Nicht ideal, da die Verwendung von Ausnahmen als Flusskontrolle im Allgemeinen eine "schlechte Sache" ist.)
quelle
true
.Reguläre Ausdrücke sind für diese Situation übertrieben. Sie können die
String.IndexOfAny()
Methode in Kombination mitPath.GetInvalidPathChars()
und verwendenPath.GetInvalidFileNameChars()
.Beachten Sie auch, dass beide
Path.GetInvalidXXX()
Methoden ein internes Array klonen und den Klon zurückgeben. Wenn Sie dies also häufig tun (tausende und tausende Male), können Sie eine Kopie des ungültigen Zeichenarrays zur Wiederverwendung zwischenspeichern.quelle
Wenn Sie nur versuchen zu überprüfen, ob eine Zeichenfolge, die Ihren Dateinamen / Pfad enthält, ungültige Zeichen enthält, besteht die schnellste Methode, die ich gefunden habe, darin,
Split()
den Dateinamen in ein Array von Teilen aufzuteilen, wo immer ein ungültiges Zeichen vorhanden ist. Wenn das Ergebnis nur ein Array von 1 ist, gibt es keine ungültigen Zeichen. :-)Ich habe versucht, diese und andere oben erwähnte Methoden 1.000.000 Mal in LinqPad für einen Datei- / Pfadnamen auszuführen.
Die Verwendung
Split()
beträgt nur ~ 850 ms.Die Verwendung
Regex("[" + Regex.Escape(new string(System.IO.Path.GetInvalidPathChars())) + "]")
dauert ca. 6 Sekunden.Die komplizierteren regulären Ausdrücke sind VIEL schlimmer, ebenso wie einige der anderen Optionen, wie die Verwendung der verschiedenen Methoden für die
Path
Klasse, um den Dateinamen abzurufen und ihre interne Validierung den Job erledigen zu lassen (höchstwahrscheinlich aufgrund des Overheads der Ausnahmebehandlung).Zugegeben, es ist nicht sehr häufig, dass Sie 1 Million Dateinamen validieren müssen, daher ist eine einzelne Iteration für die meisten dieser Methoden ohnehin in Ordnung. Aber es ist immer noch ziemlich effizient und effektiv, wenn Sie nur nach ungültigen Zeichen suchen.
quelle
Viele dieser Antworten funktionieren nicht, wenn der Dateiname zu lang ist und in einer Umgebung vor Windows 10 ausgeführt wird. Denken Sie auch darüber nach, was Sie mit Punkten tun möchten. Das Zulassen von führenden oder nachfolgenden Zeichen ist technisch gültig, kann jedoch zu Problemen führen, wenn die Datei nicht schwer zu sehen bzw. zu löschen ist.
Dies ist ein Validierungsattribut, das ich erstellt habe, um nach einem gültigen Dateinamen zu suchen.
und die Tests
quelle
Mein Versuch:
Dies ist nicht perfekt, da
Path.GetInvalidPathChars
nicht der gesamte Zeichensatz zurückgegeben wird, der in Datei- und Verzeichnisnamen ungültig ist, und natürlich gibt es noch viel mehr Feinheiten.Also benutze ich diese Methode als Ergänzung:
Es wird versucht, die Datei zu erstellen und false zurückzugeben, wenn eine Ausnahme vorliegt. Natürlich muss ich die Datei erstellen, aber ich denke, das ist der sicherste Weg, dies zu tun. Bitte beachten Sie auch, dass ich keine erstellten Verzeichnisse lösche.
Sie können auch die erste Methode verwenden, um eine grundlegende Validierung durchzuführen, und dann die Ausnahmen sorgfältig behandeln, wenn der Pfad verwendet wird.
quelle
Ich schlage vor, nur den Path.GetFullPath () zu verwenden
quelle
Ich habe diese Idee von jemandem bekommen. - Ich weiß nicht wer. Lassen Sie das Betriebssystem das schwere Heben erledigen.
quelle
Diese Prüfung
out Namen Filter mit ungültigen Zeichen (
<>:"/\|?*
und ASCII 0-31), sowie reservierten DOS - Geräte (CON
,NUL
,COMx
). Es erlaubt führende Leerzeichen und All-Dot-Namen, die mit übereinstimmenPath.GetFullPath
. (Das Erstellen einer Datei mit führenden Leerzeichen ist auf meinem System erfolgreich.)Verwendet .NET Framework 4.7.1, getestet unter Windows 7.
quelle
Ein Liner zur Überprüfung illigaler Zeichen in der Zeichenfolge:
quelle
Meiner Meinung nach besteht die einzig richtige Antwort auf diese Frage darin, zu versuchen, den Pfad zu verwenden und das Betriebssystem und das Dateisystem ihn validieren zu lassen. Andernfalls implementieren Sie nur alle Validierungsregeln, die das Betriebssystem und das Dateisystem bereits verwenden, neu (und wahrscheinlich nur unzureichend). Wenn diese Regeln in Zukunft geändert werden, müssen Sie Ihren Code entsprechend ändern.
quelle
Windows - Dateinamen sind ziemlich unrestrictive, so wirklich es nicht einmal sein könnte , dass viel von einem Problem. Die von Windows nicht zugelassenen Zeichen sind:
Sie können leicht einen Ausdruck schreiben, um zu überprüfen, ob diese Zeichen vorhanden sind. Eine bessere Lösung wäre jedoch, zu versuchen, die Dateien so zu benennen, wie der Benutzer es wünscht, und sie zu benachrichtigen, wenn ein Dateiname nicht haftet.
quelle