c# - Directory.CreateDirectory 因无效字符而失败

标签 c# .net system.io.directory

我遇到的问题是我的路径字符串通过了 Path.GetInvalidPathChars() 检查,但在尝试创建目录时失败了。

static void Main(string[] args)
{

    string str2 = @"C:\Temp\hjk&(*&ghj\config\";

    foreach (var character in System.IO.Path.GetInvalidPathChars())
    {
         if (str2.IndexOf(character) > -1)
         {

             Console.WriteLine("String contains invalid path character '{0}'", character);
             return;
         }
    }


    Directory.CreateDirectory(str2); //<-- Throws exception saying Invalid character.

    Console.WriteLine("Press any key..");
    Console.ReadKey();
}

知道可能是什么问题吗?

最佳答案

在这种情况下,文档措辞中的细微问题可能会影响我们看待或使用 API 的方式。在我们的例子中,API 的部分对我们没有多大帮助。


您还没有完全阅读 Path.GetInvalidPathChars() 上的文档:

The array returned from this method is not guaranteed to contain the complete set of characters that are invalid in file and directory names. The full set of invalid characters can vary by file system. For example, on Windows-based desktop platforms, invalid path characters might include ASCII/Unicode characters 1 through 31, as well as quote ("), less than (<), greater than (>), pipe (|), backspace (\b), null (\0) and tab (\t).

并且不要认为Path.GetInvalidFileNameChars()会立即为您带来更好的效果(我们将在下面证明这是更好的选择):

The array returned from this method is not guaranteed to contain the complete set of characters that are invalid in file and directory names. The full set of invalid characters can vary by file system. For example, on Windows-based desktop platforms, invalid path characters might include ASCII/Unicode characters 1 through 31, as well as quote ("), less than (<), greater than (>), pipe (|), backspace (\b), null (\0) and tab (\t).


在这种情况下,最好尝试 { Directory.CreateDirectory(str2); } catch (ArgumentException e) {/* 很可能路径无效 */} 而不是手动验证路径*。这将独立于文件系统工作。


当我尝试在我的 Windows 系统上创建您的目录时:

Invalid Path Characters

现在,如果我们遍历该数组中的所有字符:

foreach (char c in Path.GetInvalidPathChars())
{
    Console.WriteLine($"0x{(int)c:X4} : {c}");
}

我们得到:

0x0022 : "
0x003C : <
0x003E : >
0x007C : |
0x0000 : 
0x0001 : 
0x0002 : 
0x0003 : 
0x0004 : 
0x0005 : 
0x0006 : 
0x0007 : 
0x0008 : 
0x0009 :   
0x000A : 

0x000B : 
0x000C : 
0x000D : 
0x000E : 
0x000F : 
0x0010 : 
0x0011 : 
0x0012 : 
0x0013 : 
0x0014 : 
0x0015 : 
0x0016 : 
0x0017 : 
0x0018 : 
0x0019 : 
0x001A : 
0x001B : 
0x001C : 
0x001D : 
0x001E : 
0x001F : 

如您所见,该列表不完整。

但是:如果我们对 GetInvalidFileNameChars()

做同样的事情
foreach (char c in Path.GetInvalidFileNameChars())
{
    Console.WriteLine($"0x{(int)c:X4} : {c}");
}

我们最终得到了一个不同的列表,其中包括上述所有内容,以及:

0x003A : :
0x002A : *
0x003F : ?
0x005C : \
0x002F : /

正是我们的错误消息所指示的。在这种情况下,您可能会决定改用它。请记住我们上面的警告,Microsoft 不保证这两种方法的准确性。

当然,这并不完美,因为在 path 上使用 Path.GetInvalidFileNameChars() 会引发错误的失效(\在文件名中无效,但它在路径中完全有效!),因此您需要对此进行更正。您可以通过忽略(至少)以下字符来做到这一点:

0x003A : :
0x005C : \

您可能还想忽略以下字符(因为有时人们使用 web/*nix 样式路径):

0x002F : /

此处要做的最后一件事是演示一种稍微更简单的编写此代码的方法。 (我是 Code Review 的常客,所以这是第二天性。)

我们可以在一个表达式中完成所有事情:

System.IO.Path.GetInvalidFileNameChars().Except(new char[] { '/', '\\', ':' }).Count(c => str2.Contains(c)) > 0

使用示例:

var invalidPath = @"C:\Temp\hjk&(*&ghj\config\";
var validPath = @"C:\Temp\hjk&(&ghj\config\"; // No asterisk (*)

var invalidPathChars = System.IO.Path.GetInvalidFileNameChars().Except(new char[] { '/', '\\', ':' });

if (invalidPathChars.Count(c => invalidPath.Contains(c)) > 0)
{
    Console.WriteLine("Invalid character found.");
}
else
{
    Console.WriteLine("Free and clear.");
}

if (invalidPathChars.Count(c => validPath.Contains(c)) > 0)
{
    Console.WriteLine("Invalid character found.");
}
else
{
    Console.WriteLine("Free and clear.");
}

*:这是有争议的,如果您确定您的验证代码不会使有效路径无效,您可能想要手动验证路径。作为MikeT说:“你应该总是在获得异常之前尝试验证”。您的验证代码应与下一级验证的限制相同或更少。

关于c# - Directory.CreateDirectory 因无效字符而失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40553178/

相关文章:

C# .Where 和 .Select

java - 套接字编程 : Delay

c# - 使用StorageFile的DeleteAsync函数删除本地文件夹中的文件

C# - 检查是否可以访问/读取文件夹

c# - 我如何使filesystemwatcher触发每个文件创建的事件而不会丢失任何事件

c# - Delphi 7 和 __ArrayList

c# - 通用列表 FindAll() 与 foreach

c# - ABCPdf 使用大量内存并生成巨大文件。解决方案?

c# - 为什么我们会使用 Directory.GetFiles() 而不是 Directory.EnumerateFiles()?

c# - 使用 Path.Combine 导航目录