Frage

Wir haben mehrere .NET-Anwendungen, die mithilfe von FileSystemWatcher ein Verzeichnis auf neue Dateien überwachen.Die Dateien werden von einem anderen Ort kopiert, per FTP hochgeladen usw.Wenn die Dateien eingehen, werden sie auf die eine oder andere Weise verarbeitet.Ein Problem, für das ich jedoch nie eine zufriedenstellende Antwort gesehen habe, ist:Woher weiß man bei großen Dateien, wann in die überwachten Dateien noch geschrieben wird?Natürlich 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 dieses Problem nicht zu beheben.

War es hilfreich?

Lösung

Haben Sie versucht, eine Schreibsperre für die Datei zu erhalten?Wenn darauf geschrieben wird, sollte das fehlschlagen, und Sie wissen, dass Sie es eine Weile in Ruhe lassen sollten ...

Andere Tipps

Wenn Sie die Kontrolle über das Programm haben, das die Dateien in das Verzeichnis schreibt, können Sie das Programm die Dateien in ein temporäres Verzeichnis schreiben lassen und sie dann in das überwachte Verzeichnis verschieben.Das Verschieben sollte ein atomarer Vorgang sein, sodass der Beobachter die Datei erst sehen sollte, wenn sie sich vollständig im Verzeichnis befindet.

Wenn Sie keine Kontrolle darüber haben, was in das überwachte Verzeichnis geschrieben wird, können Sie im Watcher eine Zeit festlegen, zu der die Datei als abgeschlossen gilt, wenn sie für die angegebene Zeit dieselbe Größe beibehalten hat.Wenn die sofortige Verarbeitung kein Problem darstellt, ist die Einstellung dieses Timers auf einen relativ großen Wert eine ziemlich sichere Methode, um zu wissen, ob die Datei entweder vollständig ist oder niemals fertig sein wird.

Das „Changed“-Ereignis im FileSystemWatcher sollte erst ausgelöst werden, wenn die Datei geschlossen wird.Sieh mein Antwort 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 eingehen, aber ich halte das für etwas unwahrscheinlich.

Sofern der Inhalt einer Datei nicht auf Vollständigkeit überprüft werden kann (sie hat ein überprüfbares Format oder enthält eine Prüfsumme des Inhalts), kann nur der Absender überprüfen, ob eine ganze Datei angekommen ist.

Ich habe in der Vergangenheit eine Sperrmethode zum Senden großer Dateien per FTP verwendet.

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

Das Obige ist offensichtlich mit einem Prozess verbunden, der regelmäßig alte Dateien mit der temporären Erweiterung aufräumt.

Eine Alternative besteht darin, eine Datei mit der Länge Null mit demselben Namen, aber der zusätzlichen Erweiterung .lck zu erstellen.Sobald die echte Datei vollständig hochgeladen ist, wird die lck-Datei gelöscht.Offensichtlich ignoriert der Empfangsprozess Dateien, die den Namen einer Sperrdatei tragen.

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

Die Suche nach Dateien, die in x Minuten nicht geändert wurden, kann zu allen möglichen Problemen führen.

Die folgende Methode versucht, eine Datei mit Schreibrechten zu öffnen.Die Ausführung wird blockiert, 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);
    }
}

(aus meiner Antwort auf a verwandte Frage)

Sie müssen sich wahrscheinlich für eine Out-of-Band-Signalisierung entscheiden:Lassen Sie den Produzenten von „file.ext“ einen Dummy „file.ext.end“ schreiben.

+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 dient weniger der Sicherheit als vielmehr der Sicherstellung, dass unterwegs nichts verstümmelt wird.Wenn jemand seine eigene Datei in den großen Stream einfügen kann, kann er auch die Prüfsumme ersetzen.

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

In Windows überprüfe ich, ob eine Datei vollständig per FTP hochgeladen wurde, indem ich versuche, sie umzubenennen.Wenn das Umbenennen fehlschlägt, ist die Datei nicht vollständig.Nicht sehr elegant, das gebe ich zu, aber es funktioniert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top