Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exception codes, or detecting a "file already exists" type exception

In trying to answer this question, I was surprised to discover that attempting to create a new file when that file already exists does not throw a unique exception type, it just throws a generic IOException.

I am therefore left wondering how to determine if the IOException is the result of an existing file, or some other IO error.

The exception has an HResult, but this property is protected, and thus unavailable to me.

The only other way I can see is to pattern match the message string which feels awful.

example:

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?
}
like image 320
GazTheDestroyer Avatar asked Sep 12 '12 13:09

GazTheDestroyer


4 Answers

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"); // =)
}

Won't work for temp files etc which might have been deleted again.

Here are my exception best practices: https://coderr.io/exception-handling

like image 127
jgauffin Avatar answered Sep 27 '22 21:09

jgauffin


Edit: there is another Hresult that is used when file already exists: 0x800700B7 (-2147024713) "Cannot create a file when that file already exists". Updated the code sample.


When you try to create a new file and it already exists IOException will have Hresult = 0x80070050 (-2147024816).

So you code could look like this:

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 || 
        e.HResult == -2147024713)
    {
        // File already exists.
    }
}
like image 32
yurish Avatar answered Sep 27 '22 20:09

yurish


You can place this condition in your catch statement for IOException: if(ex.Message.Contains("already exists")) { ... }. It is a hack, but it will work for all cases that a file exists, even temporary files and such.

like image 28
ThunderGr Avatar answered Sep 27 '22 19:09

ThunderGr


To modify @jgauffin, in C# 6, you can use the File.Exists inside of the when clause to avoid entering the catch block and thus 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"))
{
   //...
}
like image 41
Arithmomaniac Avatar answered Sep 27 '22 20:09

Arithmomaniac