Мне кажется, что File.Exists() намного медленнее, когда файл не существует или у пользователя нет доступа, чем когда файл существует.
Это правда?
Это не имеет смысла для меня.
Мне кажется, что 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);
}
Я выполнил следующий тест, и на моем ПК, по крайней мере, время примерно одинаковое:
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
Файл и все его методы обычно работают с дескрипторами окон.
Если вы делаете много проверок, вы должны использовать:
FileInfo fiInfo = new FileInfo(@"c:\donotexists");
if (fiInfo.Exists)
return true;
Вместо того, чтобы работать внутри с файловыми дескрипторами, он смотрит на атрибуты файлов и намного быстрее. Кроме того, он не проверяет исключения, что является большим замедлением в .NET.