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.
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.
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).
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);
}
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?
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
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.
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.
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
@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.
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.
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.