4

I am creating a file in C# (.NET Web Service) and do not want to overwrite an existing file.

The way seems to be to construct a FileStream with FileMode.CreateNew set. It does in fact throw an exception if the file exists.

But how do I recognize this exception as opposed to other possible exceptions thrown by the file creation? The documentation at http://msdn.microsoft.com/en-us/library/47ek66wy.aspx lists this case as an "IOException" which clearly is vague as other things can cause this.

Is the answer here that I catch IOException and then just do a File.Exists?

dkeisen
  • 73
  • 6
  • 1
    You can use error code from the exception. See [How do I determine the HResult for a System.IO.IOException?](http://stackoverflow.com/questions/991537/how-do-i-determine-the-hresult-for-a-system-io-ioexception) For file exists it will be 0x80070050. – Dmitry Shkuropatsky Feb 09 '12 at 23:42
  • @DmitryShkuropatsky: You should probably make that an answer – Guvante Feb 10 '12 at 00:31

4 Answers4

5

You can get error code from the exception as the following:

int hr = Marshal.GetHRForException( ex );

For file exists it will be 0x80070050.

Dmitry Shkuropatsky
  • 3,902
  • 2
  • 21
  • 13
  • I had hoped for a cleaner answer, but had expected that reality was about like this. This does seem like the correct approach and the one I will take. Thanks, Dmitry. – dkeisen Feb 13 '12 at 18:53
0

I would recommend the other way around: do File.Exist first, then catch the exception. That way you're sure that the exception is not raised by the fact that the file already exists.

veblock
  • 1,904
  • 18
  • 10
  • 3
    That's not exactly true. Technically, it CAN be created between the check and the exception handling (rare but still possible) – colithium Feb 09 '12 at 23:34
  • Well, you're right. Technically the service can have InstanceContextMode.Single changed, plus he did not say what happens to the file outside the service. – veblock Feb 12 '12 at 21:44
0

I think the File.Exists method is the most elegant. You can play around with reflection to try and guess the root cause but it's not worth it. It's possible that InnerException is set to something more distinct. Is it null?

And the Message property should describe (in English or whatever language you're using) what exactly happened. Relying on the string returned by Message also isn't a good idea.

I like your idea best to be honest.

colithium
  • 10,269
  • 5
  • 42
  • 57
0

The best way, I believe, would be to use a File.Exists before you try to create the FileStream. Example:

if (File.Exists(path))
{
   //Handle existing file
}
else
{
   FileStream newFile = new FileStream(path, FileMode.CreateNew);
   //Logic to do with your new file
}

Trying to parse the IOException to make sure it's exactly the 'right' IOException is brittle. I believe the only way to do it is compare the IOException's comment or description.

Daryl
  • 3,253
  • 4
  • 29
  • 39
  • 1
    That's disappointing. I didn't want to use the File.Exists method as I did not want to leave a window between the check and the create. The brittleness is precisely why I asked: I know checking the message field cannot be the right answer. – dkeisen Feb 09 '12 at 23:37
  • 1
    Hmm, I see your concern. I don't know how to ensure no gap between when you check for the file and when you create it. Although it might seem brittle, I don't believe that the exception message coming from CreateNew is likely to change. If you absolutely need no gap, I'd just compare the message but make sure you document this well. Note that catching exceptions as part of your regular execution is not recommended. Therefore, I'd suggest doing a File.Exists AND a try-catch checking the IOException's message. This way, in 99% of cases the File.Exists will inform you sufficiently. – Daryl Feb 14 '12 at 20:56