2010-03-12 20 views
22

C'è un modo per verificare se una stringa destinata a un percorso ha caratteri non validi, in .Net? So che potrei scorrere su ogni carattere in Path.InvalidPathChars per vedere se il mio String ne conteneva uno, ma preferirei una soluzione semplice, forse più formale.. Net: Come faccio a cercare caratteri illegali in un percorso?

C'è uno?

ho trovato ho ancora un'eccezione se controllo solo contro Get

Aggiornamento:

ho trovato GetInvalidPathChars non copre ogni personaggio percorso non valido. GetInvalidFileNameChars ha altri 5, incluso "?", Che ho trovato. Passerò a quello, e ti riporterò se anche questo si rivelerà inadeguato.

Aggiornamento 2:

GetInvalidFileNameChars non è sicuramente quello che voglio. Contiene ':', che qualsiasi percorso assoluto deve contenere ("C: \ whatever"). Penso che dovrò usare GetInvalidPathChars dopotutto e aggiungere "?" e tutti gli altri personaggi che mi causano problemi mentre vengono fuori. Soluzioni migliori benvenute.

+0

Perché è contrassegnato con "regex"? – incarnate

+0

Non ne sono sicuro. Magnifico l'ha aggiunto. –

+0

Tag regex rimosso. –

risposta

35

InvalidPathChars è obsoleto. Utilizzare GetInvalidPathChars() invece:

public static bool FilePathHasInvalidChars(string path) 
    { 

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

Edit: Un po 'più a lungo, ma gestisce percorso vs file di caratteri non validi in una funzione:

// 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

Sono stanco ora (3AM), ma penso che IndexOfAny restituisca -1 se non viene trovato nessun char non valido, quindi il risultato è true se NO tale char viene trovato nel file filename o fileDirectory, esattamente l'opposto di ciò che si desidera. Ma, cosa più importante, come risolve "c: \ first \ second: third \ test.txt"? Prenderebbe il secondo, illegale ':'? – Avi

+0

Vedere le modifiche al post originale. Per quanto riguarda l'altra domanda, "C: \ first \ second: third \ test.txt" non contiene caratteri non validi per un percorso, poiché ":" è un carattere di percorso valido. È vero, il percorso è un percorso non valido, ma lo scopo della funzione non era quello di convalidare percorsi appropriati. Per questo, la soluzione migliore sarebbe quella di testare la stringa del percorso su un'espressione regolare. Si potrebbe anche fare: foreach (String s in path.Split ('\\')) {// test s per caratteri di file non validi} ma tale implementazione è un po 'fragile dato che devi fare un'eccezione per "C:" –

+4

La seconda funzione non sembra catturare? o * caratteri. – snarf

3

Fare attenzione quando basandosi su Path.GetInvalidFileNameChars, che non può essere affidabile come penseresti. Si noti la seguente osservazione nella documentazione MSDN su Path.GetInvalidFileNameChars:

la matrice restituita da questo metodo è non garantiti per contenere il set completo di caratteri non validi nei nomi di file e directory. Il set completo di caratteri non validi può variare in base al file system. Ad esempio, su piattaforme desktop basate su Windows, i caratteri di percorso non validi potrebbero includere caratteri ASCII/Unicode da 1 a 31, nonché preventivo ("), inferiore a (<), maggiore di (>), pipe (|), backspace (\ b), null (\ 0) e tabulazione (\ t).

non è niente di meglio con Path.GetInvalidPathChars metodo. contiene la stessa osservazione.

+1

I metodi 'GetInvalid * NameChars' non sono né utili né affidabili. La validità/invalidità del percorso è implicitamente legata al filesystem su cui il codice è in esecuzione, e dal momento che System.IO. * Non fa lo sniffing del filesystem - restituisce semplicemente un array hard coded - ciò che non è valido sul filesystem A può essere completamente filesystem B. tl; dr: non fare affidamento su questi metodi, tira il tuo. –

2

e 'probabilmente troppo tardi per voi, ma può Ho affrontato lo stesso problema e avevo bisogno di trovare un modo affidabile per disinfettare un percorso

Ecco cosa ho finito usando, in 3 passaggi:

Passaggio 1: pulizia personalizzata.

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; 
} 

Fase 2: Controllare eventuali caratteri non validi non ancora rimossi.

Un ulteriore passaggio di verifica, utilizzo il metodo Path.GetInvalidPathChars() pubblicato in precedenza per rilevare eventuali caratteri non validi non ancora rimossi.

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

Fase 3: pulire eventuali caratteri speciali rilevati al punto 2.

E, infine, ho utilizzare questo metodo come passo finale per pulire qualcosa di sinistra. (da 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)); 
} 

accedo qualsiasi carattere non valido non puliti nel primo passo. Ho scelto di andare in questo modo per migliorare il mio metodo personalizzato non appena viene rilevata una "perdita". Non posso contare sulla Path.GetInvalidFileNameChars() a causa della seguente dichiarazione di un riportato sopra (da MSDN):

"la matrice restituita da questo metodo non è garantito per contenere il set completo di caratteri non validi nel file di e la directory nomi. "

Esso non può essere la soluzione ideale, ma dato il contesto della mia applicazione e il livello di affidabilità richiesto, questa è la soluzione migliore che ho trovato.

1

ho finito di assunzione e combinando alcune implementazioni interne NET per elaborare un metodo performante:

/// <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; 
} 

Ho quindi usato in questo modo, ma anche avvolto su in un blocco try/catch per la sicurezza :

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

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

    ... 
} 
Problemi correlati