Directory.CreateDirectory失败,无效字符

时间:2016-11-11 17:25:28

标签: 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();
}

知道可能是什么问题吗?

1 个答案:

答案 0 :(得分:12)

在这些时候,文档措辞中的细微问题可能会对我们查看或使用API​​的方式产生重大影响。在我们的案例中, 部分API并没有给我们带来太多好处。

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

  

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

并且不要认为Path.GetInvalidFileNameChars()会立即对你做得更好(我们将在下面证明这是更好的选择):

  

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

在这种情况下,try { Directory.CreateDirectory(str2); } catch (ArgumentException e) { /* Most likely the path was invalid */ } 最好不要手动验证路径 *。这将独立于文件系统。

当我尝试在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.GetInvalidFileNameChars()会导致虚假失效(\在文件名中无效,但它& #39; s 在路径中完全有效!),因此您需要对此进行更正。你可以忽略(至少)以下字符来做到这一点:

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所说:&#34;你应该在获得异常之前尝试验证&#34;。您的验证代码应该与下一级验证相同或更少限制。