views:

635

answers:

6

I want to create and open a file but only if it doesnt exist. I dont want to use a File.Exists because a thread by switch after it creating a file with the same name.

How do i check if the exception System.IO.IOException was caused by the file existing? I prefer not to parse the error msg (even tho it can be as simple as .indexOf("exist"))

How should i do this?

A: 

You can use File.Open and call it with FileMode.OpenOrCreate.

Per comment: Okay, how about FileMode.CreateNew? Then, if there is one already, you will get an IOException, otherwise, make a new one.

JP Alioto
This is exactly what acidzombie24 doesn't want...
Thomas Levesque
Oh I see, you mean he does not want to open it if it's already there?
JP Alioto
He said he wants "to create and open a file but only if it doesnt exist". This is exactly what CreateNew does. I gave a +1 to compensate for the unfair -1.
Steven Sudit
@Steven : the -1 wasn't unfair... JP edited his post afterwards to add CreateNew, but initially he only mentioned OpenOrCreate ;)
Thomas Levesque
+2  A: 

You should avoid ever making logic decisions based on the contents of the Exception.Message property. That is defined to be a human-readable message, not something for a program to read. Such messages are subject to change without notice.

Human-readable messages often change to make them more readable to humans. That won't make your program any happier.


As you might be able to tell, the issue of program logic depending on human-readable messages is a pet peeve of mine - I won't tell you for how long, since that would make me feel old. This has distracted me from something that should have been obvious.

Please check to see if you get a System.IO.FileNotFoundException when the file does not exist. Try catching that instead of IOException.

John Saunders
thats exactly the problem. i have no idea how to check. I guess i could use .exist but that feels sloppy.
acidzombie24
You missed my point. Do not check the Message property, ever.
John Saunders
While I agree with the sentiment, I can think of exceptions (no pun intended).
Steven Sudit
Really? When? Maybe if it's your Message property. Otherwise, you're making a mistake that bites many, just not frequently, but has always been difficult to find and fix. I seem to remember some broken code in the transition from .NET 1.1 to .NET 2.0 - Microsoft had fixed the punctuation, and peoples' code broke as a result. Surely, Microsoft should be permitted to correct punctuation. And that completely lets localization aside...
John Saunders
"You missed my point. Do not check the Message property, ever" <-- maybe you missread it, i was going to check if the file exist via File.Exists. I dont plan to ever check the message text
acidzombie24
Ok. I see what I misread. You asked how you could check that the exception was due to the file not existing, and that you preferred not to use the message, even though it was easy. But I was thinking there is no way to check, so you'd have to use the Message.
John Saunders
+1  A: 

You could always check File.Exists()... from WITHIN the exception catch block. You don't want to check before because of threading - so check after you already know you have a problem.

Assuming you're not suddenly deleting the file from a different thread this would be an easy and obvious way of doing it.

Don't forget that the File.Exists may itself cause an exception so be sure to catch it again.

Simon_Weaver
Isn't there a race condition there?
John Saunders
there shouldnt be with the situation he described, but thats what i was hinting at with my 2nd paragraph. it could be an easy solution to his problem though
Simon_Weaver
also might need to consider what percentage of the time he expects the file to be there
Simon_Weaver
Is it possible to catch an exception in an exception?
acidzombie24
@acidzombie24 absolutely! just nest another try/catch block. just like it was any other kind of control block, such as an if or for loop
Simon_Weaver
+3  A: 

I'm not sure he wants to open the file at all if it already exists.

I think he is actually after FileMode.CreateNew this will throw an IOException if the file already exists, but otherwise will create and open it.

jerryjvl
but he was worried about other causes for the exception - such as 'permission denied' etc. the whole crux of the question was distinguishing between different possible reasons for an exception.
Simon_Weaver
The documentation on the `FileStream` constructor very strongly implies that with this mode `IOException` will only be thrown if the file already existed, otherwise you get one of the more derived (and more specific exceptions). So you are right in that the exception handler will have to check that the actual exception type is (or is not) `IOException`.
jerryjvl
+1  A: 

Why not the following?

lock(lockobj) {
    if(File.Exists(path) == false) {
        // create the file
    }
}

Are you using this as a mutex perchance? If so, there are well-defined classes specifically that.

Jason
A: 

Your best option here is to use the CreateNew option when opening the file for writing.

There is simple no reliable way to check for the existence of a file on disk. The only thing you can check for is whether or not a file used to and may still exist on disk to which the process has at least a limited form of access.

Even if you gate all access to a file from your application, you cannot reliably prevent some other application from creating / deleting the file. Even with sufficient file system level locks, users can do nefarious things like take a USB key out of the computer.

The best way to approach this type of problem is to use open options like CreateNew. This will allow the operation to only succeed if the file is not in existence at the point in time the creation is attempted. You can catch the exception at this point and attempt to infer if it was from the file existing or some other invalid access exception.

Methods like File.Exist give a false sense of security to your code base and should be closely reviewed on check in.

JaredPar