36 Stimmen

Wann ist es in Ordnung zu prüfen, ob eine Datei existiert?

Dateisysteme sind flüchtig. Das bedeutet, dass man sich nicht darauf verlassen kann, dass das Ergebnis einer Operation auch für die nächste gültig ist, selbst wenn es sich um die nächste Codezeile handelt. Sie können nicht einfach sagen if (some file exists and I have permissions for it) open the file und man kann nicht sagen if (some file does not exist) create the file . Es besteht immer die Möglichkeit, dass das Ergebnis Ihrer if Zustand wird ändern zwischen den beiden Teilen Ihres Codes. Die Operationen sind getrennt: nicht atomar.

Erschwerend kommt hinzu, dass die Art des Problems bedeutet, dass Sie, wenn Sie versucht sind, diese Prüfung vorzunehmen, wahrscheinlich bereits besorgt sind oder sich bewusst sind, dass etwas, das Sie nicht kontrollieren können, mit der Datei passieren könnte. Aufgrund der Beschaffenheit von Entwicklungsumgebungen ist es unwahrscheinlich, dass dieses Ereignis während Ihrer Tests auftritt und sehr schwer zu reproduzieren. Sie haben also nicht nur einen Fehler, sondern der Fehler wird beim Testen auch nicht auftauchen.

Daher ist es unter normalen Umständen am besten, gar nicht erst zu versuchen zu prüfen, ob eine Datei oder ein Verzeichnis existiert. Stecken Sie Ihre Entwicklungszeit stattdessen in die Behandlung von Ausnahmen aus dem Dateisystem. Sie müssen diese Ausnahmen ohnehin behandeln, so dass dies eine viel bessere Nutzung Ihrer Ressourcen ist. Auch wenn Ausnahmen langsam sind, erfordert die Überprüfung der Existenz einer Datei einen zusätzlichen Zugriff auf die Festplatte, und der Zugriff auf die Festplatte ist viel langsamer. Ich habe sogar ein gut gewähltes respuesta in einer anderen Frage zu diesem Thema.

Aber ich habe einige Zweifel. In .Net, zum Beispiel, wenn das wirklich ist immer wahr, die .Exists() Methoden wären gar nicht erst in die API aufgenommen worden. Denken Sie auch an Szenarien, in denen Sie erwarten die Ihr Programm zum Erstellen der Datei benötigt. Das erste Beispiel, das mir in den Sinn kommt, betrifft eine Desktop-Anwendung. Diese Anwendung installiert eine Standard-Benutzerkonfigurationsdatei in ihrem Home-Verzeichnis, und beim ersten Start der Anwendung kopiert jeder Benutzer diese Datei in den Anwendungsdatenordner des jeweiligen Benutzers. Es wird erwartet, dass die Datei beim ersten Start nicht vorhanden ist.

Wann ist es also akzeptabel, im Voraus zu prüfen, ob eine Datei vorhanden ist (oder andere Attribute wie Größe und Berechtigungen)? Ist es eine ausreichend gute Faustregel, beim ersten Versuch eher einen Fehlschlag als einen Erfolg zu erwarten?

1voto

Lennaert Punkte 2405

Ich würde es nur überprüfen, wenn ich erwarte, dass es fehlt (z. B. die Anwendungseinstellungen) und nur, wenn ich die Datei lesen muss.

Wenn ich in die Datei schreiben muss, handelt es sich entweder um eine Protokolldatei (so dass ich einfach an sie anhängen oder eine neue Datei erstellen kann), oder ich ersetze den Inhalt der Datei, so dass ich sie ohnehin neu erstellen kann.

Wenn ich davon ausgehe, dass die Datei existiert, wäre es richtig, dass eine Exception ausgelöst wird. Die Ausnahmebehandlung sollte dann den Benutzer informieren oder eine Wiederherstellung durchführen. Meiner Meinung nach führt dies zu einem saubereren Code.

Dateischutz (d.h. keine (möglicherweise wichtigen) Dateien zu überschreiben) ist etwas anderes, in diesem Fall würde ich immer prüfen, ob eine Datei existiert, wenn das Framework das nicht für mich tut (siehe SaveFileDialog)

1voto

JoshBerke Punkte 64214

Ich denke, die Prüfung ist sinnvoll, wenn man sicher sein will, dass die Datei überhaupt vorhanden ist. Wie Sie sagten, Einstellungsdateien... wenn es eine Datei gibt, werde ich versuchen, die vorhandenen Einstellungen zusammenzuführen, anstatt sie zu löschen.

Ein anderer Fall wäre, wenn ein Benutzer mir sagt, dass ich etwas mit einer Datei machen soll. Ja, ich weiß, dass der openFileDialog prüft, ob eine Datei existiert (aber das ist optional). Ich erinnere mich vage zurück in VB6 war dies nicht der Fall, so dass die Überprüfung der Datei existiert, dass sie gerade sagte mir zu verwenden war üblich.

Ich würde lieber nicht ausnahmsweise programmieren.

bearbeiten

Ich habe das Thema nicht verfehlt. Sie könnten versuchen, auf die Datei zuzugreifen, es wird eine Ausnahme ausgelöst, und wenn Sie dann die Datei erstellen wollen, wurde die Datei bereits dort abgelegt. Das führt nun dazu, dass Ihr Code zur Behandlung von Ausnahmen nicht mehr funktioniert. Ich denke, wir könnten dann einen Exception-Handler in unserem Exception-Handler haben, um abzufangen, dass sich die Datei noch einmal geändert hat...

Ich würde lieber versuchen, Ausnahmen zu vermeiden und sie nicht zur Kontrolle der Logik verwenden.

bearbeiten

Zusätzlich eine andere Zeit, für Attribute wie Größe zu überprüfen ist, wenn Ihr warten auf eine Datei-Operation zu beenden, ja Sie wissen nie sicher, aber mit einem guten Algorithmus und je nach dem System schreiben die Datei, die Sie in der Lage sein könnte, einen guten Teil der Fälle zu behandeln (hatte ein System laufen für fünf Jahre, die für kleine Dateien über FTP kommen überwacht, und es verwendet eine die gleiche api als das Dateisystem Watcher, und dann beginnt Polling warten auf die Datei zu stoppen, ändern, bevor Sie ein Ereignis, dass die Datei bereit ist, konsumiert werden).

0 Stimmen

+1 - Ich werde meine Antwort zu Gunsten Ihrer Antwort löschen, die meiner Meinung nach den Kern der Frage trifft :)

0 Stimmen

Sie haben nicht verstanden, worum es geht: Wenn Sie sicher sein wollen, dass die Datei vorhanden ist, sind die Vorgänge zur Überprüfung der Datei und ihre anschließende Verwendung nicht atomar. In dem Intervall kann etwas passieren.

1voto

cmsjr Punkte 52971

Das ist vielleicht zu simpel, aber ich würde denken, dass der Hauptgrund für die Überprüfung der Existenz einer Datei (daher die Existenz von .Exists()) darin besteht, unbeabsichtigtes Überschreiben bestehender Dateien zu verhindern, und nicht darin, Ausnahmen zu vermeiden, die durch den Versuch verursacht werden, auf nicht existierende oder nicht zugängliche Dateien zuzugreifen.

EDIT 2

Das war in der Tat zu simpel, und ich empfehle Ihnen, die Antwort von Stephen Martin zu lesen.

0 Stimmen

Ich bin mir bei der .Net-API nicht sicher, aber sie hat sicherlich so etwas wie O_EXCL|O_CREAT von Unix (die Datei erstellen, aber nur, wenn sie nicht existiert). Das ist atomar, so dass es nicht von jemandem überlistet werden kann, der die Datei f

0 Stimmen

Möglicherweise, aber zumindest für die Klasse System.IO.File gilt: Wenn Sie Create aufrufen und die Datei bereits existiert, wird sie ohne Benachrichtigung oder Ausnahme überschrieben (es sei denn, es wird eine andere Ausnahme ausgelöst, z. B. Datei wurde nur gelesen)

0 Stimmen

@cmsjr: das hängt davon ab, welche Methode du aufrufst und welche Parameter du verwendest. @derobert: Ich programmiere lieber nicht nach Ausnahmen und vermeide sie, wenn ich kann. Wenn ich zum Beispiel vermeiden will, eine Konfigurationsdatei zu überschreiben, ist es ein guter Schritt zu prüfen, ob sie existiert. Das ist sicher besser, als zu versuchen, sie zu erstellen und dabei eine

0voto

Robin Day Punkte 97662

Es gibt eine Reihe von möglichen Anwendungen, die Sie schreiben können, dass eine einfache File.Exists mehr als ausreichend für die Aufgabe ist. Wenn es sich um eine Konfigurationsdatei handelt, die nur von Ihrer Anwendung verwendet wird, müssen Sie es mit der Ausnahmebehandlung nicht so übertreiben.

Die von Ihnen aufgezeigten "Fehler" bei der Anwendung dieser Methode sind zwar alle berechtigt, aber das bedeutet nicht, dass sie in manchen Situationen nicht akzeptabel sind.

0voto

tvanfosson Punkte 506878

Ich denke, immer wenn Sie wissen, dass die Datei existieren kann oder nicht, und Sie eine alternative Aktion auf der Grundlage der Existenz der Datei durchführen wollen, sollten Sie die Prüfung durchführen, weil es in diesem Fall keine Ausnahmebedingung ist, dass die Datei nicht existiert. Das entbindet Sie nicht davon, Ausnahmen zu behandeln - wenn jemand anderes die Datei zwischen der Prüfung und dem Öffnen entfernt oder erstellt -, aber es macht die Absicht des Programms klar und verlässt sich nicht auf die Ausnahmebehandlung, um die Flusssteuerungslogik durchzuführen.

EDITAR : Ein Beispiel wäre die Protokollrotation beim Start.

  try
  {
       if (File.Exists("app.log"))
       {
           RotateLogs();
       }

       log = File.Open("app.log", FileMode.CreateNew );
  }
  catch (IOException)
  {
     ...another writer, perhaps?
  }
  catch (UnauthorizedAccessException)
  {
     ...maybe I should have used runas?
  }

0 Stimmen

Dadurch verdoppelt sich der Umfang des Codes und es kommt ein selten genutzter Fehlerpfad hinzu. Klingt für mich ziemlich wahrscheinlich, dass es zu Fehlern kommt.

0 Stimmen

Nein. Haben Sie einfach die Try/Catch der äußere Block sein, fangen verschiedene Ausnahmetypen als angemessen, dann tun Sie Ihre bedingte Logik innerhalb der Try-Block. Wie ist diese Verdoppelung Code - Sie wollen bereits etwas anderes basierend auf Existenz in meinem Szenario zu tun?

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