2010-03-12 3 views
22

Есть ли способ проверить, имеет ли строка, предназначенную для пути, недопустимые символы, в .Net? Я знаю, что могу перебирать каждый символ в Path.InvalidPathChars, чтобы увидеть, содержит ли моя String один, но я бы предпочел простое, возможно, более формальное решение..Net: Как проверить незаконные символы в пути?

Есть ли один?

Я нашел, что я все еще получаю исключение, если я только сверять Получить

Update:

Я нашел GetInvalidPathChars не распространяется на каждый неверный символ пути. У GetInvalidFileNameChars есть еще 5, включая '?', С которыми я столкнулся. Я собираюсь переключиться на это, и я отчитаю, если это тоже окажется неадекватным.

Update 2:

GetInvalidFileNameChars определенно не то, что я хочу. Он содержит ':', который будет содержать любой абсолютный путь («C: \ whatever»). Я думаю, что мне просто придется использовать GetInvalidPathChars в конце концов и добавить в '?' и любые другие персонажи, которые вызывают у меня проблемы по мере их появления. Лучшее решение приветствуется.

+0

Почему с тегом "regex"? – incarnate

+0

Я не уверен. Magnifico добавил. –

+0

Удалена регулярная метка. –

ответ

35

InvalidPathChars устарел. Используйте GetInvalidPathChars() вместо того, чтобы:

public static bool FilePathHasInvalidChars(string path) 
    { 

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

редактирование: Немного длиннее, но обрабатывает путь против файла недопустимых символов в одной функции:

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

Я устал сейчас (3AM), но считает, что IndexOfAny возвращает -1, если не найден недопустимый символ, поэтому результат верен, если NO такой символ найден в любом имени файла или fileDirectory, в точности противоположном желаемому. Но, что еще более важно, как это решить «c: \ first \ second: third \ test.txt»? Будет ли он поймать второй, незаконный?: '? – Avi

+0

Смотрите правки в оригинальное сообщение. Что касается вашего другого вопроса, «C: \ first \ second: third \ test.txt» не содержит недопустимых символов для пути, так как «:» является допустимым символом пути. Правда, путь является недопустимым путем, но целью этой функции является не проверка правильных путей. Для этого лучше всего было бы проверить строку пути на регулярное выражение. Вы также можете сделать: foreach (String s в path.Split ('\\')) {// проверить s для недопустимых символов файла} , но эта реализация немного хрупкая, поскольку вы должны сделать исключение для "C:" –

+4

Вторая функция, похоже, не поймает? или * символов. – snarf

3

Будьте осторожны, полагаясь на Path.GetInvalidFileNameChars, которые не могут быть столь же надежными, как вы бы подумали. Обратите внимание на следующее замечание в документации MSDN по Path.GetInvalidFileNameChars:

Массив, возвращаемый из этого метода является не гарантированно содержат полный набор символов, которые являются недействительными в именах файлов и каталогов. Полный набор недопустимых символов может отличаться в зависимости от файловой системы. Например, на платформах для настольных компьютеров Windows недопустимые символы пути могут включать символы ASCII/Unicode с 1 по 31, а также цитату («), меньше (<), больше (>), pipe (|), backspace (\ б), нуль (\ 0) и вкладку (\ т).

Это не лучше с Path.GetInvalidPathChars методом. Он содержит точно такое же замечание.

+1

Методы GetInvalid * NameChars не являются ни полезными, ни надежными. Действительность/недействительность пути неявно привязана к файловой системе, на которой выполняется код, и поскольку System.IO. * Не выполняет флюид файловой системы - просто возвращает жесткий код - то, что неверно в файловой системе A, может быть полностью действительным на файловая система B. tl; dr: не полагайтесь на эти методы, откатывайте свои собственные. –

2

Это, вероятно, слишком поздно для вас, но может помогите кому-то еще. Я столкнулся с тем же вопросом и должен был найти надежный способ дезинфекции пути.

Вот что я в конечном итоге использовал в 3 этапа:

Шаг 1: Пользовательская уборка.

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

Шаг 2: Проверьте недопустимые символы еще не удалены.

A дополнительный этап проверки, я использую метод Path.GetInvalidPathChars(), размещенный выше, для обнаружения любых потенциальных недопустимых символов, которые еще не удалены.

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

Шаг 3: Очистите специальные символы, обнаруженные на шаге 2.

И, наконец, я использую этот метод в качестве заключительного шага для очистки ничего не осталось. (от 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)); 
} 

Я вхожу любой недопустимый символ не очищено на первом этапе. Я решил пойти таким путем, чтобы улучшить свой пользовательский метод, как только обнаружена «утечка». Я не могу полагаться на Path.GetInvalidFileNameChars() из следующего утверждения Отчетного выше (из MSDN):

«Массив возвращаемой из этого метода не гарантируется содержать полный набор символов, которые являются недействительными в файле и каталог имен. "

это не может быть идеальным решением, но учитывая контекст моего приложения и уровень надежности требуется, это лучшее решение, которое я нашел.

1

я в конечном итоге заимствования и объединения нескольких внутренних .NET реализаций, чтобы придумать с производительным способом:

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

Затем я использовал это как так, но и завернул его в Try/поймать блок для безопасности :

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

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

    ... 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^