user269055
user269055

Reputation:

Why is File.Exists() much slower when the file does not exist?

Seems to me that File.Exists() is much slower when the file does not exist or the user doesn't have access than when the file does exist.

is this true?

This doesn't make sense to me.

Upvotes: 23

Views: 17662

Answers (5)

Bryan Matthews
Bryan Matthews

Reputation: 1136

File.Exists is trapping exceptions. The overhead of raising and capturing an exception may contribute to poor performance.

File.Exists works like this:

To check to see if the file exists, it tries to open the file... if an exception is thrown the file doesn't exist.

That process is slower than opening a file and no exception is thrown (which is when the file exists).

Upvotes: 49

Chris S
Chris S

Reputation: 65446

File.Exists also instantiates CLR permissioning before checking the file exists for the file. An alternative (though I haven't tried for performance) is PathFileExists if you're doing a lot of checks:

[DllImport("Shlwapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
private extern static bool PathFileExists(StringBuilder path);

void Exists()
{
    // A StringBuilder is required for interops calls that use strings
    StringBuilder builder = new StringBuilder();
    builder.Append(@"C:\test.txt");
    bool exists = PathFileExists(builder);
}

Upvotes: 34

Mark Wilkins
Mark Wilkins

Reputation: 41252

I ran the following test, and on my PC at least, the times are about the same:

  static void TestExists()
     {
     Stopwatch sw = Stopwatch.StartNew();

     for ( int i = 0; i < 1000; i++ )
        {
        if ( !File.Exists( @"c:\tmp\tmp" + i.ToString() + ".tmp" ) )
           Console.WriteLine( "File does not exist" );
        }
     Console.WriteLine( "Total for exists: " + sw.Elapsed );

     sw = Stopwatch.StartNew();
     for ( int i = 0; i < 1000; i++ )
        {
        if ( File.Exists( @"c:\tmp\tmp_" + i.ToString() + ".tmp" ) )
           Console.WriteLine( "File exists" );
        }
     Console.WriteLine( "Total for not exists: " + sw.Elapsed );
     }

The results were along the lines of the following (each run is slightly different but about the same):

Total for exists: 00:00:00.0717181
Total for not exists: 00:00:00.0824266

But across a network (on the LAN to a server one hop away), I found the test to be quite a bit slower when the files actually existed. I sniffed it and there was only one SMB packet each direction.

Total for exists: 00:00:02.4028708
Total for not exists: 00:00:00.6910531

Upvotes: 3

antesima
antesima

Reputation: 23

File and all of its methods typically work with windows file handles.

If you do a lot of checks, you should use :

FileInfo fiInfo = new FileInfo(@"c:\donotexists");
if (fiInfo.Exists)
    return true;

Rather than working internally with file handles, it looks at file attributes and is a lot more faster. Besides, it does not check for exceptions, which is a big slow-down in .NET

Upvotes: -4

Mehrdad Afshari
Mehrdad Afshari

Reputation: 422132

Generally when you search a bunch of stuff for something, you can't be sure about their lack of existence unless you have searched all possible places it could have been. When searching for something (in most kinds of collections) the worst case is when the item doesn't exist in the collection.

I have not benchmarked File.Exists in particular but I highly doubt that there's a really noticeable difference in those cases unless you're doing it thousands of times. How did you reach to this conclusion?

Upvotes: 11

Related Questions