Frage Überwachen von Dateien - So erfahren Sie, wann eine Datei vollständig ist


Wir haben mehrere .NET-Anwendungen, die ein Verzeichnis für neue Dateien mit FileSystemWatcher überwachen. Die Dateien werden von einem anderen Ort kopiert, per FTP hochgeladen usw. Wenn sie eintreffen, werden die Dateien auf die eine oder andere Weise verarbeitet. Ein Problem, für das ich noch nie eine befriedigende Antwort gefunden habe, ist: Wie kann man bei großen Dateien wissen, wann die zu überwachenden Dateien noch geschrieben werden? Offensichtlich müssen wir warten, bis die Dateien vollständig und geschlossen sind, bevor wir mit der Verarbeitung beginnen. Die Ereignisargumente in den FileSystemWatcher-Ereignissen scheinen dies nicht zu berücksichtigen.


11
2017-08-27 13:23


Ursprung


Antworten:


Haben Sie versucht, eine Schreibsperre für die Datei zu erhalten? Wenn es geschrieben wird, sollte das scheitern, und Sie wissen, es für ein bisschen zu lassen ...


1
2017-08-27 13:28



Wenn Sie die Kontrolle über das Programm haben, das die Dateien in das Verzeichnis schreibt, können Sie die Dateien in ein temporäres Verzeichnis schreiben lassen und dann in das überwachte Verzeichnis verschieben. Die Verschiebung sollte eine atomare Operation sein, daher sollte der Beobachter die Datei erst sehen, wenn sie vollständig im Verzeichnis ist.

Wenn Sie nicht kontrollieren können, was in das überwachte Verzeichnis geschrieben wird, können Sie im Watcher eine Zeit festlegen, in der die Datei als abgeschlossen gilt, wenn sie für die angegebene Zeit die gleiche Größe beibehalten hat. Wenn die sofortige Verarbeitung keine Rolle spielt, ist es relativ sicher festzustellen, ob die Datei vollständig ist oder nicht.


5
2017-08-27 13:32



Das "Changed" -Ereignis im FileSystemWatcher sollte nicht ausgelöst werden, bis die Datei geschlossen wird. Sieh mein antworte auf eine ähnliche Frage. Es besteht die Möglichkeit, dass der FTP-Download-Mechanismus die Datei während des Downloads mehrmals schließt, wenn neue Daten eintreffen, aber ich denke, das ist etwas unwahrscheinlich.


3
2017-08-27 13:31



Wenn der Inhalt einer Datei nicht verifiziert werden kann (sie hat ein verifizierbares Format oder enthält eine Prüfsumme des Inhalts), kann nur der Absender überprüfen, ob eine ganze Datei angekommen ist.

Ich habe eine Locking-Methode für das Senden von großen Dateien über FTP in der Vergangenheit verwendet.

Datei wird mit einer alternativen Erweiterung gesendet und wird umbenannt, sobald der Absender zufrieden ist.

Das Obige ist offensichtlich mit einem Prozess kombiniert, der alte Dateien periodisch mit der temporären Erweiterung aufräumt.

Eine Alternative besteht darin, eine Datei mit der Länge Null mit dem gleichen Namen und einer zusätzlichen Erweiterung .lck zu erstellen. Sobald die reale Datei vollständig hochgeladen wurde, wird die lck-Datei gelöscht. Der empfangende Prozess ignoriert offensichtlich Dateien, die den Namen einer Sperrdatei haben.

Ohne ein solches System kann der Empfänger niemals sicher sein, dass die ganze Datei angekommen ist.

Das Überprüfen auf Dateien, die in x Minuten nicht geändert wurden, ist anfällig für alle möglichen Probleme.


3
2017-08-27 13:33



Die folgende Methode versucht, eine Datei mit Schreibberechtigungen zu öffnen. Es wird die Ausführung blockieren, bis eine Datei vollständig auf die Festplatte geschrieben ist:

/// <summary>
/// Waits until a file can be opened with write permission
/// </summary>
public static void WaitReady(string fileName)
{
    while (true)
    {
        try
        {
            using (System.IO.Stream stream = System.IO.File.Open(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                if (stream != null)
                {
                    System.Diagnostics.Trace.WriteLine(string.Format("Output file {0} ready.", fileName));
                    break;
                }
            }
        }
        catch (FileNotFoundException ex)
        {
            System.Diagnostics.Trace.WriteLine(string.Format("Output file {0} not yet ready ({1})", fileName, ex.Message));
        }
        catch (IOException ex)
        {
            System.Diagnostics.Trace.WriteLine(string.Format("Output file {0} not yet ready ({1})", fileName, ex.Message));
        }
        catch (UnauthorizedAccessException ex)
        {
            System.Diagnostics.Trace.WriteLine(string.Format("Output file {0} not yet ready ({1})", fileName, ex.Message));
        }
        Thread.Sleep(500);
    }
}

(von meiner Antwort auf eine verwandte Frage)


2
2017-09-16 08:33



Sie müssen wahrscheinlich mit einer Out-of-Band-Signalisierung arbeiten: Lassen Sie den Produzenten von "file.ext" einen Dummy schreiben "file.ext.end".


1
2017-08-27 13:29



+1 für die Verwendung eines File.ext.end-Signalgebers, wenn möglich, wobei der Inhalt von file.ext.end eine Prüfsumme für die größere Datei ist. Dies ist nicht so sehr für die Sicherheit, als dafür zu sorgen, dass nichts auf dem Weg verstümmelt wird. Wenn jemand eine eigene Datei in den großen Stream einfügen kann, kann er auch die Prüfsumme ersetzen.


0
2017-08-27 13:41



Eine Schreibsperre hilft nicht, wenn der Datei-Upload teilweise fehlgeschlagen ist und der Absender noch nicht versucht hat, die Datei erneut zu senden (und erneut zu sperren).


0
2017-08-27 13:58



Die Art und Weise, wie ich Windows einchecke, wenn eine Datei vollständig von ftp hochgeladen wurde, besteht darin, sie umzubenennen. Wenn das Umbenennen fehlschlägt, ist die Datei nicht vollständig. Nicht sehr elegant, das gebe ich zu, aber es funktioniert.


0
2017-08-27 14:02