异常代码,或检测“文件已存在”类型异常

时间:2012-09-12 13:42:58

标签: c# exception ioexception

在尝试回答this question时,我惊讶地发现,当该文件已经存在时尝试创建新文件不会抛出唯一的异常类型,它只会抛出一个通用的IOException。 / p>

因此,我想知道如何确定IOException是现有文件的结果还是其他一些IO错误。

该异常有一个HResult,但此属性受到保护,因此对我无法使用。

我能看到的另一种方式是模式匹配感觉糟糕的消息字符串。

示例:

try
{
    using (var stream = new FileStream("C:\\Test.txt", FileMode.CreateNew))
    using (var writer = new StreamWriter(stream))
    {
        //write file
    }
}
catch (IOException e)
{
    //how do I know this is because a file exists?
}

8 个答案:

答案 0 :(得分:9)

try
{
    using (var stream = new FileStream("C:\\Test.txt", FileMode.CreateNew))
    using (var writer = new StreamWriter(stream))
    {
        //write file
    }
}
catch (IOException e)
{
    var exists = File.Exists(@"C:\Text.text"); // =)
}

不适用于可能已被删除的临时文件等。

答案 1 :(得分:5)

您可以将此条件放在IOException的catch语句中:if(ex.Message.Contains("already exists")) { ... }。这是一个hack,但它适用于文件存在的所有情况,甚至是临时文件等。

答案 2 :(得分:4)

当您尝试创建新文件并且它已经存在时,IOException将具有Hresult = 0x80070050 (-2147024816)

所以你的代码看起来像这样:

try
{
    using (var stream = new FileStream("C:\\Test.txt", FileMode.CreateNew))
    using (var writer = new StreamWriter(stream))
    {
        //write file
    }
}
catch (IOException e)
{
    if (e.HResult == -2147024816)
    {
        // File already exists.
    }
}

答案 3 :(得分:2)

要修改@jgauffin,在C#6中,您可以使用File.Exists子句中的when来避免输入catch块,从而behaving more like an actual dedicated exception

try
{
    using (var stream = new FileStream("C:\\Test.txt", FileMode.CreateNew))
    using (var writer = new StreamWriter(stream))
    {
        //write file
    }
}
catch (IOException e) when (File.Exists(@"C:\Text.text"))
{
   //...
}

答案 4 :(得分:0)

你应该使用

FileMode.Create

而不是

FileMode.CreateNew

如果文件已存在,它将覆盖该文件。

答案 5 :(得分:0)

你做不到。不幸的是,由于我在.NET框架中理解的原因,没有进一步指定IOExceptions。

但是在创建新文件的情况下,通常的做法是先检查文件是否存在。像这样:

       try
        {
            if (File.Exists("C:\\Test.txt"))
            {
                //write file

                using (var stream = new FileStream("C:\\Test.txt", FileMode.CreateNew))
                using (var writer = new StreamWriter(stream))
                {
                    //The actual writing of file

                }

            }
        }
        catch (IOException ex)
        {
            //how do I know this is because a file exists?
            Debug.Print(ex.Message);
        }

也许不是你想要的答案。但是,c'est ca。

答案 6 :(得分:0)

这不是100%万无一失(IOException有其他原因),但您至少可以排除所有派生的异常类型:

try
{
    ...
}
catch(IOException e)
{
    if (e is UnauthorizedAccessException) throw;
    if (e is DirectoryNotFoundException) throw;
    if (e is PathTooLongException) throw;
    // etc for other exceptions derived from IOException

    ... assume file exists
}

或同等的:

try
{
    ...
}
catch(UnauthorizedAccessException)
{
    throw;
}
catch(DirectoryNotFoundException)
{
    throw;
}
catch(PathTooLongException)
{
    throw;
}
catch(IOException e)
{
    ... assume file exists
}

关于链接的问题,我只是检查是否存在,提示用户覆盖,然后使用OpenOrCreate覆盖它是否存在。我认为大多数应用程序都是以这种方式工作的,即使存在覆盖在错误时刻创建的文件的理论风险。

答案 7 :(得分:0)

在C#6和更高版本中:

const int WARN_WIN32_FILE_EXISTS = unchecked((int)0x80070050);

try
{
    ...
}
catch (IOException e) when (e.HResult == WARN_WIN32_FILE_EXISTS)
{
    ...
}

...或when (e.HResult == -2147024816),如果您要“快速而不可穿透”。 ;-)

(FWIW,Mono忠实地复制了以Windows为中心的错误代码,并且在Mac / Linux上也可以使用。)