当文件不存在时,为什么File.Exists()会慢得多?

在我看来,当文件不存在或者用户没有访问权时文件存在时,File.Exists()要慢得多。

这是真的?

这对我来说没有意义。

一般来说,当你搜索一堆东西时,除非你已经搜索了所有可能存在的地方 ,否则你无法确定它们是否存在。 当搜索某些东西(在大多数类型的集合中)时,最糟糕的情况是该集合中不存在该项目。

我没有特别对File.Exists进行基准测试,但我非常怀疑在这些情况下存在明显的差异,除非你做了数千次。 你是如何得出这个结论的?

File.Exists正在捕获exception。 提升和捕获exception的开销可能导致性能不佳。

File.Exists工作方式如下:

要检查文件是否存在,它会尝试打开文件…如果抛出exception,则文件不存在。

该过程比打开文件慢,并且不会抛出任何exception(即文件存在时)。

File.Exists还会在检查文件存在的文件之前实例化CLR权限。 如果你做了很多检查,另一种选择(虽然我没有尝试过性能)是PathFileExists :

 [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); } 

我运行了以下测试,至少在我的电脑上,时间大致相同:

  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 ); } 

结果如下(每次运行略有不同,但大致相同):

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

但是通过一个网络(在局域网上到服务器一跳之后),我发现当文件确实存在时,测试速度会慢一些。 我闻了闻,每个方向只有一个SMB数据包。

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

文件及其所有方法通常与Windows文件句柄一起使用。

如果你做了很多检查,你应该使用:

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

它不是在内部使用文件句柄,而是查看文件属性,速度要快得多。 此外,它不会检查exception,这在.NET中是一个很大的减速