.Net:如何检查路径中的非法字符?

Mik*_*ras 28 .net path illegal-characters

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

有吗?

我发现如果我只检查Get,我仍会得到一个例外

更新:

我发现GetInvalidPathChars不会覆盖每个无效的路径字符.GetInvalidFileNameChars还有5个,包括'?',我遇到过.我要改用它,我会报告它是否也证明是不合适的.

更新2:

GetInvalidFileNameChars绝对不是我想要的.它包含':',任何绝对路径将包含("C:\ whatever").我想我毕竟不得不使用GetInvalidPathChars,并添加'?' 以及任何其他导致我出现问题的角色.欢迎提供更好的解

Jer*_*ell 40

不推荐使用InvalidPathChars.改为使用GetInvalidPathChars():

    public static bool FilePathHasInvalidChars(string path)
    {

        return (!string.IsNullOrEmpty(path) && path.IndexOfAny(System.IO.Path.GetInvalidPathChars()) >= 0);
    }
Run Code Online (Sandbox Code Playgroud)

编辑:稍长,但在一个函数中处理路径与文件无效字符:

    // 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;
    }
Run Code Online (Sandbox Code Playgroud)

  • 第二个功能似乎没有抓住?或*字符. (4认同)

Ren*_*ené 8

依赖 时要小心Path.GetInvalidFileNameChars,它可能不像你想象的那么可靠。请注意 MSDN 文档中的以下注释Path.GetInvalidFileNameChars

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

Path.GetInvalidPathChars方法也好不到哪里去。它包含完全相同的注释。

  • `GetInvalid*NameChars` 方法既无用也不可靠。路径有效性/无效性与代码正在执行的文件系统隐式绑定,并且由于 System.IO.* 不进行文件系统嗅探 - 只返回一个硬编码数组 - 文件系统 A 上的无效内容可能完全有效文件系统 B. tl; dr:不要依赖这些方法,自己动手。 (2认同)

Ran*_*den 5

我最终借用并组合了一些内部 .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;
}
Run Code Online (Sandbox Code Playgroud)

然后我像这样使用它,但为了安全起见,也将它包装在 try/catch 块中:

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

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

    ...
}
Run Code Online (Sandbox Code Playgroud)


Gle*_*den 5

.NET 4.7.2 开始Path.GetInvalidFileNameChars()报告以下 41 个“坏”字符。

0x0000 0 '\0' | 0x000d 13 '\r' | 0x001b 27 '\u001b'
0x0001 1 '\u0001' | 0x000e 14 '\u000e' | 0x001c 28 '\u001c'
0x0002 2 '\u0002' | 0x000f 15 '\u000f' | 0x001d 29 '\u001d'
0x0003 3 '\u0003' | 0x0010 16 '\u0010' | 0x001e 30 '\u001e'
0x0004 4 '\u0004' | 0x0011 17 '\u0011' | 0x001f 31 '\u001f'
0x0005 5 '\u0005' | 0x0012 18 '\u0012' | 0x0022 34 '"'
0x0006 6 '\u0006' | 0x0013 19 '\u0013' | 0x002a 42 '*'
0x0007 7 '\a' | 0x0014 20 '\u0014' | 0x002f 47 '/'
0x0008 8 '\b' | 0x0015 21 '\u0015' | 0x003a 58 ':'
0x0009 9 '\t' | 0x0016 22 '\u0016' | 0x003c 60 '<'
0x000a 10 '\n' | 0x0017 23 '\u0017' | 0x003e 62 '>'
0x000b 11 '\v' | 0x0018 24 '\u0018' | 0x003f 63 '?'
0x000c 12 '\f' | 0x0019 25 '\u0019' | 0x005c 92 '\\'
                        | 0x001a 26 '\u001a' | 0x007c 124 '|'

正如指出的另一个海报,这是一个真超集合通过返回的字符的Path.GetInvalidPathChars()

以下函数检测上面显示的 41 个字符的确切集合:

public static bool IsInvalidFileNameChar(Char c) => c < 64U ?
        (1UL << c & 0xD4008404FFFFFFFFUL) != 0 :
        c == '\\' || c == '|';
Run Code Online (Sandbox Code Playgroud)