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?

38voto

Stephen Martin Punkte 9256

Die Methode File.Exists dient in erster Linie dazu, das Vorhandensein einer Datei zu prüfen, wenn Sie nicht beabsichtigen, die Datei zu öffnen. Zum Beispiel, um das Vorhandensein einer Sperrdatei zu prüfen, deren Existenz etwas aussagt, deren Inhalt aber unwichtig ist.

Wenn Sie die Datei öffnen wollen, müssen Sie jede Ausnahme behandeln, unabhängig von den Ergebnissen der vorherigen Aufrufe von File.Exists. Es hat also im Allgemeinen keinen wirklichen Wert, diese Methode unter diesen Umständen aufzurufen. Verwenden Sie einfach den entsprechenden FileMode-Aufzählungswert in Ihrer open-Methode und behandeln Sie alle Ausnahmen, so einfach ist das.

EDIT: Auch wenn dies in Bezug auf die .Net-API ausgedrückt wird, basiert es auf der zugrunde liegenden System-API. Sowohl Windows als auch Unix haben Systemaufrufe (z. B. CreateFile), die das Äquivalent der FileMode-Aufzählung verwenden. In .Net (oder Mono) wird der FileMode-Wert einfach an den zugrunde liegenden Systemaufruf weitergegeben.

0 Stimmen

Ich möchte noch hinzufügen, dass ich File.Exists oft verwende. In der Regel in einem "wenn !existieren holen es aus dem Netzwerk als .tmp dann fix Dateiname" Muster.

6voto

supercat Punkte 72939

Generell gilt, dass Methoden wie File.Exists oder Eigenschaften wie WeakReference.Alive o SomeConcurrentQueue.Count sind nicht nützlich, um sicherzustellen, dass ein "guter" Zustand existiert, können aber nützlich sein, um festzustellen, dass ein "schlechter" Zustand existiert, ohne unnötige (und möglicherweise kontraproduktive) Arbeit zu leisten. Solche Situationen können in vielen Szenarien auftreten, die mit Sperren (und Dateien, da diese oft Sperren enthalten) zu tun haben. Da alle Routinen, die auf eine Gruppe von Ressourcen sperren müssen, wenn möglich immer in einer konsistenten Reihenfolge Sperren auf diese Ressourcen erwerben sollten, kann es notwendig sein, eine Sperre auf eine Ressource zu erwerben, von der erwartet wird, dass sie existiert, bevor eine Ressource erworben wird, die möglicherweise existiert oder auch nicht. In einem solchen Szenario ist es zwar unmöglich, die Möglichkeit zu vermeiden, dass man die erste Ressource sperrt, die zweite Sperre nicht erwirbt und dann die erste Sperre freigibt, ohne irgendeine nützliche Arbeit mit ihr verrichtet zu haben, aber die Überprüfung der Existenz der zweiten Ressource vor dem Erwerb der Sperre für die erste Ressource würde unnötigen und nutzlosen Aufwand minimieren.

0 Stimmen

@Adriano: Mit ziemlicher Sicherheit. My response was written long after any of the others, but since none of them mentioned the usefulness of a "cheap" test which can distinguish between "object <i>is</i> in a bad state" and "object <i>might be</i> in a good state", I thought it worth writing a new answer. Eine etwas parallele Situation besteht bei der Prüfung, ob eine <i>WeakReference</i> noch aktiv ist. Der Test ist nicht nützlich, um zu prüfen, ob eine Referenz noch aktiv ist, aber er ist nützlich, wenn man eine Aktion durchführen will, wenn sie es nicht ist.

1 Stimmen

@Adriano: Wenn man eine Aktion mit einer WeakReference wenn sie noch aktiv ist, sollte man sie kopieren Target Eigenschaft auf eine Variable übertragen und prüfen, ob sie null '; selbst wenn zwischen der Kopie und dem Test eine GC stattfindet, wird das Objekt durch das Kopieren des Ziels vor der Erfassung geschützt. Wenn man andererseits eine Aktion nur durchführen möchte, wenn das Objekt abgeholt wurde, sollte man die IsAlive Eigenschaft, um zu vermeiden, dass man versehentlich die Lebensdauer eines Objekts verlängert, das man so schnell wie möglich sterben lassen möchte, wenn es nicht mehr gebraucht wird.

5voto

Mitch Wheat Punkte 287474

Es hängt von Ihren Anforderungen ab, aber eine Möglichkeit ist, eine exklusiv open file handle, mit einer Art Wiederholungsmechanismus. Sobald Sie dieses Handle haben, wird es für einen anderen Prozess schwer (oder unmöglich) sein, diese Datei zu löschen (oder zu verschieben).

Ich habe Code in .NET verwendet, der dem folgenden ähnelt, um ein exklusives Dateihandle zu erhalten, bei dem ich erwarte, dass ein anderer Prozess möglicherweise die Datei schreibt:

FileInfo fi = new FileInfo(fullFilePath);

int attempts = maxAttempts;
do
{
    try
    {
        // Asking to open for reading with exclusive access...
        fs = fi.Open(FileMode.Open, FileAccess.Read, FileShare.None);
    }
    // Ignore any errors... 
    catch {}

    if (fs != null)
    {
        break;
    }
    else
    {
        Thread.Sleep(100);
    }
}
while (--attempts > 0);

1 Stimmen

Dies gilt zwar für Windows, nicht aber für *nix. Root und in vielen Fällen auch normale Benutzer können Dateien nach Belieben löschen/verschieben, unabhängig davon, wie sie geöffnet sind. Oftmals hat es nicht einmal Auswirkungen auf den Handle. Die Windows-Dateisperre ist so ärgerlich, wenn eine Anwendung sie nicht loslässt... bitte befürworten Sie nicht noch mehr davon.

2 Stimmen

@rmeador: Machen Sie sich nicht lächerlich. Es gibt Zeiten, in denen eine exklusive Sperre notwendig ist!

4 Stimmen

Da ich von einem Unix-Hintergrund komme, ist der einzige Grund, warum eine Dateisperre wie in Windows überhaupt benötigt wird, ein System, das einen Dateinamen und eine Datei als untrennbar betrachtet. Unix tut das nicht.

2voto

derobert Punkte 47691

Ein Beispiel: Sie können prüfen, ob Dateien vorhanden sind, die Sie nicht öffnen können (z. B. aufgrund von Berechtigungen).

Ein anderes, möglicherweise besseres Beispiel: Sie wollen prüfen, ob eine Unix-Gerätedatei vorhanden ist. Aber öffnen Sie sie auf keinen Fall; das Öffnen hat Nebeneffekte (z.B. öffnen/schließen /dev/st0 spult das Band zurück)

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.

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