C# 如何在不使用try-catch的情况下检查路径是否有效?

C# 如何在不使用try-catch的情况下检查路径是否有效?,c#,exception-handling,path,directory,C#,Exception Handling,Path,Directory,我想检查文件夹是否存在,如果不存在,则创建它。但我不知道提供的路径是否有效。当路径无效时,会发生以下情况 string path = "this is an invalid path"; if (!Directory.Exists(path)) Directory.CreateDirectory(path); //Exception thrown here 如果提供无效路径,它将抛出DirectoryNotFoundException异常 如何阻止此异常的发生?我不想用试一试的方法。

我想检查文件夹是否存在,如果不存在,则创建它。但我不知道提供的路径是否有效。当路径无效时,会发生以下情况

string path = "this is an invalid path";

if (!Directory.Exists(path))
    Directory.CreateDirectory(path); //Exception thrown here
如果提供无效路径,它将抛出
DirectoryNotFoundException
异常

如何阻止此异常的发生?我不想用试一试的方法。我想在异常发生之前检测此异常是否会发生。

使用方法检查文件夹是否存在

if(Directory.Exists(path))
{
  //Directory exists
}
else
{
 // doesn't exist
}

记住包括
System.IO

代码失败的原因是路径无效。文件说:

目录NotFoundException

指定的路径无效(例如,它位于 未映射驱动器)

试图提前预测是否可以创建目录是件麻烦事。您需要考虑安全性、操作系统名称规则和限制、文件系统名称规则和限制,以及驱动器是否映射。可能还有更多的担忧。我不会考虑重新实施该系统免费提供的内容

在任何情况下,虽然您可以调用
目录.Exists
,但仍然需要允许引发异常。如果文件系统在调用
Directory.Exists
和随后调用
Directory.CreateDirectory
之间发生更改,则将引发异常。例如,如果另一个进程创建了您尝试创建的目录。诚然,这是一个不太可能发生的事件,但完全有可能


总之,最好的选择是捕获异常。正如众所周知的谚语所说,请求原谅比请求允许要好。

你可以使用一个if-else语句

if(!Directory.Exists(path))
   Directory.CreateDirectory(path)
else
   //Show user a custom error message

您还可以使用
Path.GetInvalidFileNameChars()
检查提供的目录名是否对新目录名有效:

// Directory.Exists will return false because path is not even valid
var path = "1:1 comparison?";
var firstBad = Path.GetInvalidFileNameChars().Cast<char?>()
                   .FirstOrDefault(c => path.Contains(c.Value));
if (firstBad != null)
    Console.WriteLine("Char '{0}' is invalid for a directory name", firstBad.Value);
//Directory.Exists将返回false,因为路径甚至无效
var path=“1:1比较?”;
var firstBad=Path.GetInvalidFileNameChars().Cast()
.FirstOrDefault(c=>path.Contains(c.Value));
if(firstBad!=null)
WriteLine(“Char'{0}'对于目录名无效”,firstBad.Value);

为什么不捕获(特定)异常?这被认为是一个很好的实践。。。总之,这些是我的解决方案,没有try/catch:

  • 解决方案:

    string path = "C:\test";
    if (!Directory.Exists(path) && path.IndexOfAny(Path.GetInvalidFileNameChars()) == -1)
    {
        Directory.CreateDirectory(path);
    }
    
    string path = "C:\test";
    var canCreate = true;
    foreach (var c in path.Where(Path.GetInvalidFileNameChars().Contains))
    {
        canCreate = false;
    }
    
    if (canCreate && !Directory.Exists(path))
    {
        Directory.CreateDirectory(path);
    }
    
    if (path.Any(c => Path.GetInvalidFileNameChars().Contains(c)) && !Directory.Exists(path))
    {
        Directory.CreateDirectory(path);
    }
    
  • 解决方案:

    string path = "C:\test";
    if (!Directory.Exists(path) && path.IndexOfAny(Path.GetInvalidFileNameChars()) == -1)
    {
        Directory.CreateDirectory(path);
    }
    
    string path = "C:\test";
    var canCreate = true;
    foreach (var c in path.Where(Path.GetInvalidFileNameChars().Contains))
    {
        canCreate = false;
    }
    
    if (canCreate && !Directory.Exists(path))
    {
        Directory.CreateDirectory(path);
    }
    
    if (path.Any(c => Path.GetInvalidFileNameChars().Contains(c)) && !Directory.Exists(path))
    {
        Directory.CreateDirectory(path);
    }
    
  • 解决方案:

    string path = "C:\test";
    if (!Directory.Exists(path) && path.IndexOfAny(Path.GetInvalidFileNameChars()) == -1)
    {
        Directory.CreateDirectory(path);
    }
    
    string path = "C:\test";
    var canCreate = true;
    foreach (var c in path.Where(Path.GetInvalidFileNameChars().Contains))
    {
        canCreate = false;
    }
    
    if (canCreate && !Directory.Exists(path))
    {
        Directory.CreateDirectory(path);
    }
    
    if (path.Any(c => Path.GetInvalidFileNameChars().Contains(c)) && !Directory.Exists(path))
    {
        Directory.CreateDirectory(path);
    }
    
  • 请注意,此代码仍可能失败。。。e、 考虑一下SecurityExption(你有在那里创建目录的证书吗

    还要注意,在使用Exists()进行测试之后,但在调用CreateDirectory()之前,仍然有(一点)可能(由另一个进程/线程/…)创建了目录。这是两个调用,在查询/修改文件系统时,它们不是原子的(一起)。

    试试这个

    string path=“这是一个无效路径”


    我认为在C#中测试路径是否有效以及文件是否存在而不引发异常的最简单方法是直接在shlwapi.dll中调用非托管函数

    [DllImport("shlwapi.dll", EntryPoint = "PathFileExistsW",  SetLastError = true, CharSet = CharSet.Unicode)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool PathFileExists([MarshalAs(UnmanagedType.LPTStr)]string pszPath);
    

    请注意,正如David在中所写,当您尝试创建目录时,可能会出现异常。

    检查Hi David的这一可能的副本,我不确定您将如何执行此操作?如何才能在甚至无效的路径上获取父目录。请查看我修订的问题。尝试重新编写所有层的代码是毫无意义的f检查。捕获异常。这并不能阻止异常的发生,无论如何尝试这样做都是不好的。问题是如果路径无效,如何避免引发异常,但如果路径包含在
    GetInvalidPathChars
    中定义的一个或多个无效字符,则
    IsPathRooted
    会引发异常为流量控制设置例外情况绝对不是好的做法()。不幸的是,.Net framework在某些情况下几乎不可避免。@Ian Goldby是的,不是为了流量控制。但他要求IO和安全操作,并且在这里被认为是捕获特定异常的最佳实践,如果他希望这样做,可能会将其包装在自己的无异常IO方法中。无论如何,这不是一项巨大的工作-/control flow在这里,我看不到不简单地捕捉异常并以C#中的典型方式进行操作,并以“不同”的方式进行操作而不需要这样做的好处。他要求的事情是不可能的(afaik),检查不是原子性的。那么,为什么不捕获并继续执行真正重要的逻辑呢?@Ian Goldby It只是简单地接受这样一个事实:它不是原子性的,查询的结果是陈旧的,并且可能不正确/下一个操作的结果可能不相同(如果不存在目录检查和创建),然后捕获(罕见的?)案例和处理。这应该不会对这个低级别函数的业务逻辑产生太大影响。如果异常经常发生……那么您可能会考虑为什么/您在做什么,因为这似乎是一个默认案例,并且“架构”有问题方法。我认为我们从务实的角度来看是同意的。我只是指出,仅仅因为.NET强制您使用异常进行流控制,它并不能成为“最佳实践”。(这更像是一种必要的邪恶,通过只捕获特定的异常而稍微减轻了一点。)