Hallo,
Ich möchte Festellen ob eine Datei sich geändert hat.
dazu habe ich den WatchService von java.nio implementiert. Dass Problem ist, das ich einen ENTRY_MODIFY bekomme sobald die Datei zum Lesen geöffnet wurde.
Lösungsansatz: Warten bis die Datei 2mal geändert wurde. Nachteil: Die Datei könnte 2mal kurz nacheinander geöffnet werden.
Lösungsansatz: Check summen errechnen. Nachteil: Braucht sehr lange (ich will fiele Dateien Überwachen).
Diese Diskussion hatten wir schon mal. Je nach Betriebssystem sind die Events sehr unterschiedlich… Es gibt da keine schoene Loesung. MD5 Hash nehmen ist sicherlich die beste Loesung.
ein ENTRY_MODIFY sollte eigentlich nicht geworfen werden, nur wenn man eine Datei ließt.
Es sei den natürlich, das lesende Programm legt eine temp-Datei im überwachten Ordner ab.
Damit du diese Fälle abfangen kannst, brauchts du erstmal eine Liste mit allen Dateien, die überwacht werden sollen.
Ich gehe mal davon aus, daß du in deinem Code folgendes machst:
for (WatchEvent<?> event : DeinWatchKeyObjekt.pollEvents())
{
//Irgendwas
}
In dieser For-Schleife kommst du mit
WatchEvent<Path> ev = (WatchEvent<Path>) event;
Path filename = ev.context();
an den Dateinamen von der Datei, die geändert wurde.
Wenn der Dateiname mit einem aus deiner Liste mit den überwachten Dateien übereinstimmt, dann…
Wenn du in deiner Liste noch das letzte Zugriffsdatum und die Dateigröße vermerkst und diese mit dem aktuellen Zustand der Datei abgleichst, solltest du die meisten unnötigen ENTRY_MODIFY herausfiltern können.
Allerdings wirst du trotzdem unter Umständen mehrere ENTRY_MODIFYs für eine Datei bekommen. Das hängt einerseits vom verwendeten Betriebsystem ab, andererseits mit was für einem Programm du die Datei bearbeitest.
(Um eine Prüfsumme wirst du nicht herumkommen, wenn du es ganz eindeutig haben willst.)
ohne jetzt wirklich einen sinnvollen beitrag leisten zu können :
ich frage mich bei solchen themen immer wieder warum leute auf solche ideen kommen und was der sinn dahinter sein soll
mir fällt kein wirklich sinnvolles anwendungsbeispiel ein in dem es mich interessiert ob sich der inhalt einer datei ändert
und auch wenn ich mögliche szenarien durchspiele finde ich irgendwie immer ne andere lösung
meistens läuft es darauf hinaus : logs mitlesen
lösung : log-output-stream des prozesses direkt abgreifen und ggf durchschleußen damit das ganze auch wieder im file landet
stellt die API keine möglichkeit ist es wohl auch nicht gedacht mit den logs in realtime irgendwas zu machen
schutz vor manipulation > es soll verhindert werden das daten verändert werden
sehr einfache lösung : LOCK drauf setzen, prüfen ob alles korrekt ist und dann LOCK halten (ich find es immer wieder banane warum viele programme ein .lck file nutzen um einen LOCK zu emulieren, wobei dann meist selbst das lck-file selbst nicht mal einen ordentlich LOCK hat)
ein LOCK ist deutlich einfacher als ständig zu prüfen ob die daten noch korrekt sind
mir fällt nicht mal ein drittes szenario ein in dem es wirklich sinnvoll wäre eine datei oder meinetwegen auch einen ganzen ordner zur runtime in realtime zu überwachen
ihr könnte mich ja gerne korrigieren, aber einen wirklich sinnvollen anwendungsfall gibt es nicht (weshalb es mich wundert das OS/FS überhaupt solche events losfeuern)
Es kommt selbst heute noch häufig vor, das Maschinen nur mit Hilfe von Dateien mit einem Management-Programm kommunizieren können bzw. daß das die einzige Schnittstelle ist. Entweder man schaut alle x Sekunden bzw. Minuten nach, ob sich was an der Datei geändert hat, oder man läßt sich informieren, wenn sich was geändert hat. (Letzteres wäre natürlich eleganter und resourcenschonender.)
So was ist z. B. bei Druckmaschinen noch ganz normal.
Ist zwar alles andere als modern und praktisch, aber solange die Hersteller keinen Schlußstrich unter diese Altlasten ziehen…
@Timothy_Truckle
in einem solchen fall wäre event-basiertes update deutlich eleganter (was mit sicherheit auch realisierbar ist obwohl ich von beiden keine ahnung habe) @cmrudolph
was bitte soll daran effizient sein ein verzeichnis zu beobachten ob sich dort änderungen ereignen ? irgendwie versteh ich das beispiel leider überhaupt nicht
und wenn du schon mit effizienz kommst : für sowas wäre ne ordentliche datenbank besser
(wobei ich bei einer mail-software schon eher von ausgehe das diese auch “korrekt” implementiert und genutzt wird, also über sockets oder ein event system)
@hansmueller
wenn mans auf übertreiben würde könnte man an dieses beispiel auch alte lochkarten-leser anpassen in dem man sagt : er versucht so lange ne karte zu pollen bis wieder welche verfügbar sind , was ja einem loop der ständig ein verzeichnis scant gleich kommt
event-basiert umgebogen wäre ein schalter der dem einzug signalisiert : karte vorhanden , und das ganze ding dann erst losläuft
wie ihr seht : auch für die gebrachten beispiele gäbe es (zumindest aus meiner sicht) möglichkeiten ständiges pollen zu vermeiden
sicher : WatchService geht schon in die richtige richtung in dem auf FS-events reagiert wird statt zu pollen
worauf ich aber mit meinem post hinaus wollte : warum sollte es sinnvoll sein wirklich diesen speziellen fall, ein verzeichnis oder ein file darauf zu überwachen ob änderungen gemacht werden, ständig zu überprüfen
ich bau das beispiel mit den log-files mal um : ein FTP-server
was wäre wohl “sinnvoller” : ständiges pollen nach neuen uploads oder den server so zu implementieren das er bei einem upload ein event auslöst ?
sicher : ist dies nicht möglich da man z.b. selbst nicht der entwickler ist wird einem kaum was anderes übrig bleiben, aber solche in meinen augen dirty-würg-a-raunds nur weils “einfacher” geht ? hmmm, ich zweifel irgendwie dran
[QUOTE=Unregistriert]
was bitte soll daran effizient sein ein verzeichnis zu beobachten ob sich dort änderungen ereignen ? irgendwie versteh ich das beispiel leider überhaupt nicht
und wenn du schon mit effizienz kommst : für sowas wäre ne ordentliche datenbank besser
(wobei ich bei einer mail-software schon eher von ausgehe das diese auch „korrekt“ implementiert und genutzt wird, also über sockets oder ein event system)[/QUOTE]
Ok, da habe ich mich vielleicht etwas zu undeutlich ausgedrückt. Dass die Kommunikation über Verzeichnisse erfolgt hat Kompatibilitätsgründe. Die Zustellung von Mails und die Auslieferung an den Client geschehen normalerweise durch verschiedene Daemons (beispielsweise procmail und Dovecot). Damit die sich alle verstehen, hat man sich auf einen Dateisystemorientierten Austausch geeinigt (unter Unix ist ja sowieso alles eine Datei, daher naheliegend), mbox und später dann maildir - wobei beides noch im Einsatz ist.
Damit der MDA feststellen kann, dass eine neue Mail angekommen ist, müssen Änderungen im Dateisystem festgestellt werden.
Mit „Das macht die Software erst effizient.“ meinte ich, dass eine Benachrichtigung vom Betriebssystem, wenn sich das Dateisystem geändert hat, deutlich effizienter ist als regelmäßig ggf. recht große Verzeichnisstrukturen auf Veränderungen zu scannen.
Ein weiteres Beispiel, wo eine Betriebssystembenachrichtigung sinnvoll ist, ist DropBox.
wie ihr seht : auch für die gebrachten beispiele gäbe es (zumindest aus meiner sicht) möglichkeiten ständiges pollen zu vermeiden
Ich glaube, wir haben aneinander vorbeigeredet. Ich habe argumentiert, weshalb eine asynchrone Benachrichtigung sinnvoll im Gegensatz zum Polling ist. Denn genau das wird bei „modernen“ Betriebssystemen vom [japi]WatchService[/japi] umgesetzt.
Siehe dazu die Doku vom WatchService:
The implementation that observes events from the file system is intended to map directly on to the native file event notification facility where available, or to use a primitive mechanism, such as polling, when a native facility is not available.