【发布时间】:2010-02-08 22:36:33
【问题描述】:
在我看来,当文件不存在或用户无权访问时,File.Exists() 比文件存在时慢得多。
这是真的吗?
这对我来说没有意义。
【问题讨论】:
在我看来,当文件不存在或用户无权访问时,File.Exists() 比文件存在时慢得多。
这是真的吗?
这对我来说没有意义。
【问题讨论】:
File.Exists 正在捕获异常。引发和捕获异常的开销可能会导致性能下降。
File.Exists 是这样工作的:
要检查文件是否存在,它会尝试打开文件...如果抛出异常,则文件不存在。
该过程比打开文件慢,并且没有抛出异常(即文件存在时)。
【讨论】:
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);
}
【讨论】:
通常,当您在一堆东西中搜索某样东西时,您无法确定它们不存在,除非您搜索了所有可能的地方。在搜索某物时(在大多数类型的集合中),最坏的情况是该项目在集合中不存在。
我没有特别对 File.Exists 进行基准测试,但我非常怀疑这些情况下是否存在真正明显的差异,除非你这样做了数千次。您是如何得出这个结论的?
【讨论】:
List<T>.Contains比较。
File.Exists 中使用了什么类型的路径?是绝对像C:\Windows\Notepad.exe 还是像.\My\File.txt?
我进行了以下测试,至少在我的 PC 上,时间大致相同:
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
但是通过网络(在 LAN 上到一跳外的服务器),当文件实际存在时,我发现测试要慢很多。我闻了一下,每个方向只有一个 SMB 数据包。
Total for exists: 00:00:02.4028708
Total for not exists: 00:00:00.6910531
【讨论】:
File 及其所有方法通常适用于 Windows 文件句柄。
如果你做了很多检查,你应该使用:
FileInfo fiInfo = new FileInfo(@"c:\donotexists");
if (fiInfo.Exists)
return true;
它不是在内部处理文件句柄,而是查看文件属性并且速度更快。此外,它不检查异常,这在 .NET 中是一个很大的减速
【讨论】:
FileInfo.Exists 最终与File.Exists 发出相同的调用。 (使用Reflector可以看到它必须执行FillAttributeInfo并打开一个SafeFindHandle,就像File.Exists一样)。