2010-03-12 79 views
22

有没有办法来检查一个路径的字符串是否有无效的字符,在净?我知道我可以迭代Path.InvalidPathChars中的每个字符来查看我的字符串是否包含一个字符,但我更喜欢简单的,也许更正式的解决方案。.Net:如何检查路径中的非法字符?

有没有?

我发现我仍然得到一个异常,如果我只核对获取

更新:

我发现GetInvalidPathChars并不涵盖所有路径无效字符。 GetInvalidFileNameChars还有5个,包括'?',我遇到过。我将转向那个,如果它也被证明是不够的,我会报告回来。

更新2:

GetInvalidFileNameChars绝对不是我想要的。它包含任何绝对路径将包含的“:”(“C:\ whatever”)。我想我只需要使用GetInvalidPathChars,并添加'?'和任何其他字符,当他们出现时会引起我的问​​题。更好的解决方案,

+0

为什么标记为“正则表达式”? – incarnate 2010-03-12 21:17:02

+0

我不确定。 Magnifico补充说。 – 2010-03-12 21:31:22

+0

删除了正则表达式标签。 – 2010-03-12 22:09:00

回答

35

InvalidPathChars已弃用。在一个函数稍长,但处理路径VS文件无效字符:使用GetInvalidPathChars()代替:

public static bool FilePathHasInvalidChars(string path) 
    { 

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

编辑依托Path.GetInvalidFileNameChars时,可能不会像可靠

// 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,因此如果在文件名或fileDirectory中找不到这样的字符,结果是正确的,正好与想要的相反。 但是,更重要的是,它如何解决“c:\ first \ second:third \ test.txt”?它会抓住第二个非法的':'吗? – Avi 2010-04-01 23:46:54

+0

查看修改原始帖子。 至于你的其他问题,“C:\ first \ second:third \ test.txt”不包含路径的任何无效字符,因为“:”是一个有效的路径字符。诚然,路径是无效的路径,但该功能的目的不是验证正确的路径。为此,最好的办法是根据正则表达式测试路径字符串。 你也可以这样做: foreach(String s in path.Split('\\')){//测试s为无效文件字符} 但这个实现有点脆弱,因为你必须为“C:” – 2010-04-02 13:54:06

+4

第二个函数似乎没有捕获?或*字符。 – snarf 2011-06-14 23:37:39

3

要小心你会想。注意MSDN文档中的以下言论上Path.GetInvalidFileNameChars

数组此方法返回的不保证包含一套完整的文件名和目录名无效字符。全套无效字符可能因文件系统而异。例如,在基于Windows的桌面平台上,无效路径字符可能包含ASCII/Unicode字符1到31以及引号(“),小于(<),大于(>),管道(|),退格符( \ b),空(\ 0)和标签(\ t)。

这不是任何更好地与Path.GetInvalidPathChars方法,它包含完全相同的言论。

+1

'GetInvalid * NameChars'方法既不实用也不可靠。路径有效性/无效性隐含地与执行代码的文件系统相关联,并且由于System.IO。*不执行文件系统嗅探 - 仅返回一个硬编码数组 - 文件系统A上无效的内容可能完全有效文件系统B. tl; dr:不要依靠这些方法,自己推出。 – 2013-12-17 18:28:48

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步:检查所有无效字符尚未删除。

一个额外的验证步骤,我使用上面发布的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)); 
} 

我登陆的第一步没有清理任何无效字符。一旦检测到“泄漏”,我会选择这种方式来改进我的自定义方法。我不能依靠,因为下面的语句报告的上方(从MSDN)上的Path.GetInvalidFileNameChars()

“数组此方法返回不能保证包含 一套完整的文件无效字符和目录 名字。“

它可能不是理想的解决方案,但考虑到我的应用程序的背景和可靠性要求的水平,这是我找到了最好的解决方案。

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/catch块包裹起来:

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

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

    ... 
} 
相关问题