21 Stimmen

Warum ist File.Exists() viel langsamer, wenn die Datei nicht existiert?

Mir scheint, dass File.Exists() viel langsamer ist, wenn die Datei nicht existiert oder der Benutzer keinen Zugriff darauf hat, als wenn die Datei existiert.

Ist das wahr?

Das ergibt für mich keinen Sinn.

47voto

Bryan Matthews Punkte 1108

File.Exists fängt Ausnahmen ab. Der Overhead beim Auslösen und Abfangen einer Ausnahme kann zu einer schlechten Leistung beitragen.

File.Exists funktioniert folgendermaßen:

Um zu prüfen, ob die Datei vorhanden ist, wird versucht, die Datei zu öffnen. Wenn eine Ausnahme ausgelöst wird, existiert die Datei nicht.

Dieser Vorgang ist langsamer als das Öffnen einer Datei, und es wird keine Ausnahme ausgelöst (was der Fall ist, wenn die Datei existiert).

34voto

Chris S Punkte 63542

File.Exists instanziiert auch die CLR-Berechtigung, bevor die Datei auf ihre Existenz überprüft wird. Eine Alternative (die ich allerdings aus Leistungsgründen nicht ausprobiert habe) ist PathFileExists wenn Sie viele Kontrollen durchführen:

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

11voto

mmx Punkte 400975

Wenn man in einem Haufen Sachen nach etwas sucht, kann man im Allgemeinen nicht sicher sein, dass es nicht existiert, es sei denn, man hat nach etwas gesucht alle möglichen Orte es hätte sein können. Bei der Suche nach etwas (in den meisten Arten von Sammlungen) ist der schlimmste Fall, dass das Objekt in der Sammlung nicht vorhanden ist.

Ich habe kein Benchmarking durchgeführt File.Exists aber ich bezweifle stark, dass es in diesen Fällen einen wirklich spürbaren Unterschied gibt, es sei denn, man macht es tausende Male. Wie sind Sie zu diesem Schluss gekommen?

0 Stimmen

Nehmen wir eine Datei, die zwar existiert, auf die der Benutzer aber keinen Zugriff hat. Wäre der Ablauf nicht derselbe, wie wenn der Benutzer Zugriff hätte? d.h.: einen Zeiger auf die Datei erhalten und die Berechtigungen prüfen? Oder vielleicht verhindern die Berechtigungen das Auffinden der Datei, um die Berechtigungen zu prüfen, und es erscheint eine leere Liste? oder das Gleiche, was Sie beschreiben, tritt auf, wenn Sie die Berechtigungen prüfen? ich glaube, das ergibt langsam Sinn. Vielen Dank

0 Stimmen

Ja, Genehmigungen sind eine weitere Sammlung, nach der gesucht werden muss. Wenn Sie finden, was Sie suchen, können Sie sofort aufgeben, aber wenn Sie nicht finden, was Sie suchen, müssen Sie alle Möglichkeiten abhaken.

0 Stimmen

Ich kam zu dieser Schlussfolgerung, weil ich File.Exists() für Tausende von Dateien aus einer Quellliste überprüfen musste. Mit der Zeit stellte ich fest, dass der Prozess länger dauerte, je mehr Dateien fehlten. In einem kleineren Kontext ist der Unterschied nicht wirklich spürbar.

3voto

Mark Wilkins Punkte 39992

Ich habe den folgenden Test durchgeführt, und zumindest auf meinem PC sind die Zeiten ungefähr gleich:

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

Die Ergebnisse sahen wie folgt aus (jeder Durchlauf ist etwas anders, aber ungefähr gleich):

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

Aber in einem Netzwerk (im LAN zu einem Server, der einen Sprung entfernt ist) war der Test um einiges langsamer, als die Dateien tatsächlich existierten. Ich habe es gesnifft und es gab nur ein SMB-Paket in jede Richtung.

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

1 Stimmen

Dieser Test ist nicht sehr zuverlässig, da Sie auch die Ausgabe auf der Konsole messen.

0 Stimmen

@t3chb0t: Die angezeigte Leistung ist die Gesamtleistung. Ich habe mich nicht klar ausgedrückt, aber die erste Schleife lief mit vorhandenen Dateien (also keine Ausgabe aus dieser Schleife) und die zweite für Dateien, die nicht vorhanden waren (also keine Ausgabe). Die Zeitmessung beinhaltete also keine Konsolenausgabe. Die Zahlen wären viel größer gewesen, wenn sie 1000 Zeilen Konsolenausgabe enthalten hätten.

-4voto

antesima Punkte 23

File und alle seine Methoden arbeiten in der Regel mit Windows-Dateihandles.

Wenn Sie viele Prüfungen durchführen, sollten Sie :

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

Anstatt intern mit Datei-Handles zu arbeiten, werden die Dateiattribute betrachtet, was wesentlich schneller ist. Außerdem prüft es nicht auf Ausnahmen, was in .NET eine große Verlangsamung darstellt.

1 Stimmen

Es sieht so aus FileInfo.Exists macht letztlich die gleichen Aufrufe wie File.Exists . (Anhand von Reflector können Sie sehen, dass er Folgendes ausführen muss FillAttributeInfo und öffnen Sie eine SafeFindHandle , genau wie File.Exists ).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X