Подтвердить что ты не робот

Почему File.Exists() намного медленнее, когда файл не существует?

Мне кажется, что File.Exists() намного медленнее, когда файл не существует или у пользователя нет доступа, чем когда файл существует.

Это правда?

Это не имеет смысла для меня.

4b9b3361

Ответ 1

Обычно, когда вы ищете что-то для чего-то, вы не можете быть уверены в их отсутствии существования, если не будете искать все возможные места, которые могли бы быть. При поиске чего-либо (в большинстве видов коллекций) наихудший случай - когда элемент не существует в коллекции.

В частности, я не тестировал File.Exists, но я очень сомневаюсь, что там действительно заметная разница в тех случаях, если вы делаете это тысячи раз. Как вы пришли к такому выводу?

Ответ 2

File.Exists - это исключения захвата. Накладные расходы на сбор и сбор исключений могут способствовать снижению производительности.

File.Exists работает следующим образом:

Чтобы проверить, существует ли файл, он пытается открыть файл... если генерируется исключение, файл не существует.

Этот процесс работает медленнее, чем открытие файла, и исключение не генерируется (это когда файл существует).

Ответ 3

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

Ответ 4

Я выполнил следующий тест, и на моем ПК, по крайней мере, время примерно одинаковое:

  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

Ответ 5

Файл и все его методы обычно работают с дескрипторами окон.

Если вы делаете много проверок, вы должны использовать:

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

Вместо того, чтобы работать внутри с файловыми дескрипторами, он смотрит на атрибуты файлов и намного быстрее. Кроме того, он не проверяет исключения, что является большим замедлением в .NET.