2010-03-12 4 views
22

Gibt es eine Möglichkeit zu überprüfen, ob ein String, der für einen Pfad gedacht ist, ungültige Zeichen in .Net hat? Ich weiß, ich könnte über jedes Zeichen in Path.InvalidPathChars iterieren, um zu sehen, ob mein String eins enthält, aber ich würde eine einfache, vielleicht formellere Lösung bevorzugen..Net: Wie überprüfe ich auf unzulässige Zeichen in einem Pfad?

Gibt es eins?

ich gefunden habe ich immer noch eine Ausnahme, wenn ich nur gegen

Aktualisierung Holen Sie überprüfen:

Ich habe GetInvalidPathChars gefunden werden nicht alle ungültigen Pfad Zeichen abdecken. GetInvalidFileNameChars hat 5 weitere, einschließlich '?', Die mir schon begegnet sind. Ich werde darauf umsteigen, und ich melde mich zurück, wenn es sich ebenfalls als unangemessen erweist.

Update 2:

GetInvalidFileNameChars ist definitiv nicht das, was ich will. Es enthält ':', was jeder absolute Pfad enthalten wird ("C: \ was auch immer"). Ich denke, ich werde GetInvalidPathChars nur noch verwenden und '?' und andere Charaktere, die mir Probleme bereiten, wenn sie auftauchen. Bessere Lösungen willkommen.

+0

Warum ist es mit "regex" getaggt? – incarnate

+0

Ich bin mir nicht sicher. Magnifico hat es hinzugefügt. –

+0

Regex-Tag entfernt. –

Antwort

35

InvalidPathChars ist veraltet. Verwenden Sie GetInvalidPathChars() statt:

public static bool FilePathHasInvalidChars(string path) 
    { 

     return (!string.IsNullOrEmpty(path) && path.IndexOfAny(System.IO.Path.GetInvalidPathChars()) >= 0); 
    } 

Edit: Etwas länger, aber Griffe Pfad vs Datei ungültige Zeichen in einer Funktion:

// WARNING: Not tested 
    public static bool FilePathHasInvalidChars(string path) 
    { 
     bool ret = false; 
     if(!string.IsNullOrEmpty(path)) 
     { 
      try 
      { 
       // Careful! 
       // Path.GetDirectoryName("C:\Directory\SubDirectory") 
       // returns "C:\Directory", which may not be what you want in 
       // this case. You may need to explicitly add a trailing \ 
       // if path is a directory and not a file path. As written, 
       // this function just assumes path is a file path. 
       string fileName = System.IO.Path.GetFileName(path); 
       string fileDirectory = System.IO.Path.GetDirectoryName(path); 

       // we don't need to do anything else, 
            // if we got here without throwing an 
            // exception, then the path does not 
            // contain invalid characters 
      } 
      catch (ArgumentException) 
      { 
            // Path functions will throw this 
            // if path contains invalid chars 
       ret = true; 
      } 
     } 
     return ret; 
    } 
+0

Ich bin jetzt müde (3 Uhr), aber ich denke, dass IndexOfAny -1 zurückgibt, wenn kein ungültiges Zeichen gefunden wird, daher ist das Ergebnis wahr, wenn KEIN solches Zeichen entweder in Dateiname oder Dateiverzeichnis gefunden wird, genau das Gegenteil von dem, was gewünscht wird. Aber was noch wichtiger ist, wie löst das "c: \ first \ second: third \ test.txt"? Würde es das zweite, illegale ':' fangen? – Avi

+0

Siehe Änderungen am ursprünglichen Post. Zu Ihrer anderen Frage enthält "C: \ first \ second: third \ test.txt" keine ungültigen Zeichen für einen Pfad, da ":" ein gültiges Pfadzeichen ist. True, der Pfad ist ein ungültiger Pfad, aber der Zweck der Funktion bestand nicht darin, korrekte Pfade zu validieren. Am besten wäre es, die Pfadzeichenfolge mit einem regulären Ausdruck zu testen. Sie könnten auch tun: foreach (String s in path.Split ('\\')) {// Test s für ungültige Datei Zeichen} aber diese Implementierung ist ein wenig brüchig, da Sie eine Ausnahme für die machen müssen "C:" –

+4

Die zweite Funktion scheint nicht zu fangen? oder * Zeichen. – snarf

3

Seien Sie vorsichtig, wenn Sie auf Path.GetInvalidFileNameChars angewiesen, die nicht so zuverlässig sein kann, wie du würdest denken. Beachten Sie die folgende Bemerkung in der MSDN-Dokumentation auf Path.GetInvalidFileNameChars:

Das Array von dieser Methode zurück ist nicht garantiert den vollständigen Satz von Zeichen enthalten, die in Datei- und Verzeichnisnamen ungültig sind. Der vollständige Satz ungültiger Zeichen kann je nach Dateisystem variieren. (|) Beispielsweise auf Windows-basierten Desktop-Plattformen, ungültiger Pfad Zeichen könnten ASCII/Unicode-Zeichen 1 bis 31 sowie Anführungszeichen ("), kleiner als (<), größer als (>), Rohr umfassen, Backspace (\ b), null (\ 0) und Tabulator (\ t).

Es ist nicht besser mit Path.GetInvalidPathChars Methode. Es enthält genau die gleiche Bemerkung.

+1

Die Methoden 'GetInvalid * NameChars' sind weder nützlich noch verlässlich. Pfadvalidität/-invalidität ist implizit mit dem Dateisystem verbunden, auf dem der Code ausgeführt wird, und da System.IO. * Kein Dateisystem-Sniffing ausführt - gibt nur ein fest codiertes Array zurück - was im Dateisystem A ungültig ist, kann vollständig gültig sein Dateisystem B. tl; dr: Verlassen Sie sich nicht auf diese Methoden, rollen Sie Ihre eigenen. –

2

Es ist wahrscheinlich zu spät für Sie, aber kann hilf mir jemand anderen. Ich sah das gleiche Problem und musste eine zuverlässige Möglichkeit finden, einen Weg zu sanieren.

Hier ist, was ich in drei Schritten verwendet:

Schritt 1: Benutzerdefinierte Reinigung.

public static string RemoveSpecialCharactersUsingCustomMethod(this string expression, bool removeSpecialLettersHavingASign = true) 
{ 
    var newCharacterWithSpace = " "; 
    var newCharacter = ""; 

    // Return carriage handling 
    // ASCII LINE-FEED character (LF), 
    expression = expression.Replace("\n", newCharacterWithSpace); 
    // ASCII CARRIAGE-RETURN character (CR) 
    expression = expression.Replace("\r", newCharacterWithSpace); 

    // less than : used to redirect input, allowed in Unix filenames, see Note 1 
    expression = expression.Replace(@"<", newCharacter); 
    // greater than : used to redirect output, allowed in Unix filenames, see Note 1 
    expression = expression.Replace(@">", newCharacter); 
    // colon: used to determine the mount point/drive on Windows; 
    // used to determine the virtual device or physical device such as a drive on AmigaOS, RT-11 and VMS; 
    // used as a pathname separator in classic Mac OS. Doubled after a name on VMS, 
    // indicates the DECnet nodename (equivalent to a NetBIOS (Windows networking) hostname preceded by "\\".). 
    // Colon is also used in Windows to separate an alternative data stream from the main file. 
    expression = expression.Replace(@":", newCharacter); 
    // quote : used to mark beginning and end of filenames containing spaces in Windows, see Note 1 
    expression = expression.Replace(@"""", newCharacter); 
    // slash : used as a path name component separator in Unix-like, Windows, and Amiga systems. 
    // (The MS-DOS command.com shell would consume it as a switch character, but Windows itself always accepts it as a separator.[16][vague]) 
    expression = expression.Replace(@"/", newCharacter); 
    // backslash : Also used as a path name component separator in MS-DOS, OS/2 and Windows (where there are few differences between slash and backslash); allowed in Unix filenames, see Note 1 
    expression = expression.Replace(@"\", newCharacter); 
    // vertical bar or pipe : designates software pipelining in Unix and Windows; allowed in Unix filenames, see Note 1 
    expression = expression.Replace(@"|", newCharacter); 
    // question mark : used as a wildcard in Unix, Windows and AmigaOS; marks a single character. Allowed in Unix filenames, see Note 1 
    expression = expression.Replace(@"?", newCharacter); 
    expression = expression.Replace(@"!", newCharacter); 
    // asterisk or star : used as a wildcard in Unix, MS-DOS, RT-11, VMS and Windows. Marks any sequence of characters 
    // (Unix, Windows, later versions of MS-DOS) or any sequence of characters in either the basename or extension 
    // (thus "*.*" in early versions of MS-DOS means "all files". Allowed in Unix filenames, see note 1 
    expression = expression.Replace(@"*", newCharacter); 
    // percent : used as a wildcard in RT-11; marks a single character. 
    expression = expression.Replace(@"%", newCharacter); 
    // period or dot : allowed but the last occurrence will be interpreted to be the extension separator in VMS, MS-DOS and Windows. 
    // In other OSes, usually considered as part of the filename, and more than one period (full stop) may be allowed. 
    // In Unix, a leading period means the file or folder is normally hidden. 
    expression = expression.Replace(@".", newCharacter); 
    // space : allowed (apart MS-DOS) but the space is also used as a parameter separator in command line applications. 
    // This can be solved by quoting, but typing quotes around the name every time is inconvenient. 
    //expression = expression.Replace(@"%", " "); 
    expression = expression.Replace(@" ", newCharacter); 

    if (removeSpecialLettersHavingASign) 
    { 
     // Because then issues to zip 
     // More at : http://www.thesauruslex.com/typo/eng/enghtml.htm 
     expression = expression.Replace(@"ê", "e"); 
     expression = expression.Replace(@"ë", "e"); 
     expression = expression.Replace(@"ï", "i"); 
     expression = expression.Replace(@"œ", "oe"); 
    } 

    return expression; 
} 

Schritt 2: Überprüfen Sie alle ungültige Zeichen noch nicht entfernt.

Als zusätzlichen Verifizierungsschritt verwende ich die oben angegebene Methode Path.GetInvalidPathChars(), um mögliche ungültige Zeichen zu finden, die noch nicht entfernt wurden.

public static bool ContainsAnyInvalidCharacters(this string path) 
{ 
    return (!string.IsNullOrEmpty(path) && path.IndexOfAny(Path.GetInvalidPathChars()) >= 0); 
} 

Schritt 3: Reinigen Sie alle Sonderzeichen in Schritt erkannt 2.

Und schließlich, verwende ich diese Methode als letzten Schritt etwas übrig zu reinigen. (von How to remove illegal characters from path and filenames?):

public static string RemoveSpecialCharactersUsingFrameworkMethod(this string path) 
{ 
    return Path.GetInvalidFileNameChars().Aggregate(path, (current, c) => current.Replace(c.ToString(), string.Empty)); 
} 

mir jedes ungültigen Zeichen Protokoll nicht in dem ersten Schritt gereinigt. Ich wähle diesen Weg, um meine benutzerdefinierte Methode zu verbessern, sobald ein "Leck" entdeckt wird. Ich kann es nicht, weil die folgenden Aussage über die Path.GetInvalidFileNameChars() verlassen ein gemeldete oben (von MSDN):

„Das Array von dieser Methode zurückgegeben wird, nicht den vollständigen Satz von Zeichen enthalten garantiert, die in der Datei sind ungültig und Verzeichnis Namen. "

Es kann nicht die ideale Lösung sein, aber der Rahmen meiner Anwendung und das Niveau der Zuverlässigkeit erforderlich gegeben, dies ist die beste Lösung, die ich gefunden.

1

Ich landete Anleihe- und ein paar internen .NET-Implementierungen kombiniert mit einem performanten Verfahren zu kommen:

/// <summary>Determines if the path contains invalid characters.</summary> 
/// <remarks>This method is intended to prevent ArgumentException's from being thrown when creating a new FileInfo on a file path with invalid characters.</remarks> 
/// <param name="filePath">File path.</param> 
/// <returns>True if file path contains invalid characters.</returns> 
private static bool ContainsInvalidPathCharacters(string filePath) 
{ 
    for (var i = 0; i < filePath.Length; i++) 
    { 
     int c = filePath[i]; 

     if (c == '\"' || c == '<' || c == '>' || c == '|' || c == '*' || c == '?' || c < 32) 
      return true; 
    } 

    return false; 
} 

ich es dann wie so verwendet, sondern auch wickelte es für die Sicherheit in einem try/catch-Block nach oben :

if (!string.IsNullOrWhiteSpace(path) && !ContainsInvalidPathCharacters(path)) 
{ 
    FileInfo fileInfo = null; 

    try 
    { 
     fileInfo = new FileInfo(path); 
    } 
    catch (ArgumentException) 
    {    
    } 

    ... 
}