Ich möchte benachrichtigt werden, wenn eine Datei im Dateisystem geändert wurde. Ich habe nur einen Thread gefunden, der die lastModified File-Eigenschaft abfragt, und diese Lösung ist eindeutig nicht optimal.
Vielen Dank für alle Antworten. Da meine Anforderungen gering sind (ich muss nur eine in meiner Webanwendung geänderte Eigenschaftendatei neu laden. Hauptsächlich, weil der Neustart der gesamten Webanwendung etwas langsam ist), bleibe ich beim Umfragemodell. Zumindest weiß ich jetzt, dass es für diese Fälle keine einfache Lösung gibt.
Cheng81
14
Nur eine Notiz. Als wir dieses Problem lösten, stellten wir fest, dass große Dateien in der Regel langsam eingehen, und der Abfragemechanismus entdeckte häufig eine neue oder geänderte Datei, bevor sie vollständig geschrieben wurde. Um dies zu lösen, wurde eine Zwei-Biss-Lösung eingeführt. Der Poller bemerkte, dass sich eine Datei geändert hatte, benachrichtigte das System jedoch nicht über eine neue / geänderte Datei, bis sie für zwei Polls gleich aussah: dh sich stabilisiert hatte. Viele Badfile-Fehler wurden behoben.
Steve Powell
1
Abgesehen davon leidet Tomcat unter diesem Problem, wenn große WAR-Dateien aus Remote-Quellen in den Ordner webapps abgelegt werden, und das schon lange.
John Rix
Antworten:
21
Auf der niedrigen Ebene besteht die einzige Möglichkeit, dieses Dienstprogramm zu modellieren, darin, einen Thread in einem Verzeichnis abzufragen und die Attribute der Datei zu überwachen. Sie können jedoch Muster verwenden, um einen Adapter für ein solches Dienstprogramm zu entwickeln.
Beispielsweise verfügen j2ee-Anwendungsserver wie Tomcat und andere über eine Funktion zum automatischen Laden, bei der die Anwendung neu gestartet wird, sobald sich der Deployment-Deskriptor oder die Servlet-Klasse ändert.
Sie können die Bibliotheken von solchen Servern verwenden, da der größte Teil des Codes von Tomcat wiederverwendbar und OpenSource ist.
Dies gilt nicht mehr für Java 7: Es gibt jetzt eine API dafür, die sich in die Benachrichtigungsdienste des Betriebssystems einbinden kann
Arnout Engelen
Diese API ist äußerst unzureichend und bietet keine Benachrichtigung für Ereignisse zum Schließen von Dateien unter Linux. In einem einfachen Fall funktioniert das Kopieren einer Datei in ein anderes Verzeichnis nicht, wenn sie geschlossen wird.
binarytemple_picsolve
117
Ich habe bereits einen Protokolldateimonitor geschrieben und festgestellt, dass die Auswirkung der Abfrage der Attribute einer einzelnen Datei einige Male pro Sekunde auf die Systemleistung tatsächlich sehr gering ist.
Ich sehe die Beispiele als Beobachtungsverzeichnis, aber was ist mit einer einzelnen Datei?
Archimedes Trajano
@ArchimedesTrajano Die API benachrichtigt Sie, wenn sich eine Datei in einem Verzeichnis geändert hat. Das ausgelöste Ereignis enthält den Namen der Datei, die geändert wurde. So können Sie Ereignisse für eine bestimmte Datei oder Dateien verarbeiten und andere ignorieren.
Es gibt eine Bibliothek namens jnotify , die inotify unter Linux umschließt und auch Windows unterstützt. Ich habe es nie benutzt und weiß nicht, wie gut es ist, aber es ist einen Versuch wert, würde ich sagen.
Es funktioniert perfekt und ist super einfach zu bedienen. Ich benutze inotify seit vielen Jahren. Es ist schnell, stabil und zuverlässig
am
8
Java commons-io verfügt über einen FileAlterationObserver . Es führt eine Abfrage in Kombination mit einem FileAlterationMonitor durch. Ähnlich wie bei Commons VFS. Der Vorteil ist, dass es viel weniger Abhängigkeiten hat.
Bearbeiten: Weniger Abhängigkeiten sind nicht wahr, sie sind für VFS optional. Es wird jedoch Java-Datei anstelle der VFS-Abstraktionsschicht verwendet.
"Weitere NIO-Funktionen" verfügt über eine Dateiüberwachungsfunktion, deren Implementierung vom zugrunde liegenden Betriebssystem abhängt. Sollte in JDK7 sein.
Könnten Sie genauer sein oder einen Link zur Dokumentation posten? Ich kann anscheinend nichts dazu finden ...
Luciano
Es scheint das Paket zu sein java.nio.file. Siehe ein Tutorial .
David L.
4
Ich führe dieses Codeausschnitt jedes Mal aus, wenn ich die Eigenschaftendatei lese, und lese die Datei nur dann tatsächlich, wenn sie seit dem letzten Lesen geändert wurde. Hoffe das hilft jemandem.
privatelong timeStamp;privateFile file;privateboolean isFileUpdated(File file ){this.file = file;this.timeStamp = file.lastModified();if(this.timeStamp != timeStamp ){this.timeStamp = timeStamp;//Yes, file is updatedreturntrue;}//No, file is not updatedreturnfalse;}
Ein ähnlicher Ansatz wird in Log4J verwendet FileWatchdog.
Wenn Sie bereit sind, sich von etwas Geld zu trennen, ist JNIWrapper eine nützliche Bibliothek mit einem Winpack. Sie können Dateisystemereignisse für bestimmte Dateien abrufen. Leider nur Windows.
Andernfalls ist der Rückgriff auf nativen Code nicht immer schlecht, insbesondere wenn das beste Angebot ein Abfragemechanismus gegenüber einem nativen Ereignis ist.
Ich habe festgestellt, dass Java-Dateisystemvorgänge auf einigen Computern langsam sein und die Leistung der Anwendung leicht beeinträchtigen können, wenn sie nicht richtig gehandhabt werden.
Sie können auch die Apache Commons JCI (Java Compiler Interface) in Betracht ziehen. Obwohl sich diese API auf die dynamische Kompilierung von Klassen zu konzentrieren scheint, enthält sie auch Klassen in ihrer API, die Dateiänderungen überwachen.
Es gibt eine kommerzielle Cross-Desktop-Bibliothek für Dateien und Ordner namens JxFileWatcher. Es kann hier heruntergeladen werden:
http://www.teamdev.com/jxfilewatcher/
Das Abrufen der zuletzt geänderten Dateieigenschaft ist jedoch eine einfache, aber effektive Lösung. Definieren Sie einfach eine Klasse, die my erweitert, FileChangedWatcherund implementieren Sie die onModified()Methode:
Ähnlich wie bei den anderen Antworten habe ich Folgendes mit File, Timer und TimerTask gemacht, damit dies in festgelegten Intervallen als Hintergrund-Thread-Abfrage ausgeführt wird.
Antworten:
Auf der niedrigen Ebene besteht die einzige Möglichkeit, dieses Dienstprogramm zu modellieren, darin, einen Thread in einem Verzeichnis abzufragen und die Attribute der Datei zu überwachen. Sie können jedoch Muster verwenden, um einen Adapter für ein solches Dienstprogramm zu entwickeln.
Beispielsweise verfügen j2ee-Anwendungsserver wie Tomcat und andere über eine Funktion zum automatischen Laden, bei der die Anwendung neu gestartet wird, sobald sich der Deployment-Deskriptor oder die Servlet-Klasse ändert.
Sie können die Bibliotheken von solchen Servern verwenden, da der größte Teil des Codes von Tomcat wiederverwendbar und OpenSource ist.
quelle
Ich habe bereits einen Protokolldateimonitor geschrieben und festgestellt, dass die Auswirkung der Abfrage der Attribute einer einzelnen Datei einige Male pro Sekunde auf die Systemleistung tatsächlich sehr gering ist.
Java 7 hat als Teil von NIO.2 die WatchService-API hinzugefügt
quelle
Ich verwende die VFS-API von Apache Commons. Hier ist ein Beispiel für die Überwachung einer Datei ohne großen Einfluss auf die Leistung:
DefaultFileMonitor
quelle
Es gibt eine Bibliothek namens jnotify , die inotify unter Linux umschließt und auch Windows unterstützt. Ich habe es nie benutzt und weiß nicht, wie gut es ist, aber es ist einen Versuch wert, würde ich sagen.
quelle
Java commons-io verfügt über einen FileAlterationObserver . Es führt eine Abfrage in Kombination mit einem FileAlterationMonitor durch. Ähnlich wie bei Commons VFS. Der Vorteil ist, dass es viel weniger Abhängigkeiten hat.
Bearbeiten: Weniger Abhängigkeiten sind nicht wahr, sie sind für VFS optional. Es wird jedoch Java-Datei anstelle der VFS-Abstraktionsschicht verwendet.
quelle
"Weitere NIO-Funktionen" verfügt über eine Dateiüberwachungsfunktion, deren Implementierung vom zugrunde liegenden Betriebssystem abhängt. Sollte in JDK7 sein.
quelle
java.nio.file
. Siehe ein Tutorial .Ich führe dieses Codeausschnitt jedes Mal aus, wenn ich die Eigenschaftendatei lese, und lese die Datei nur dann tatsächlich, wenn sie seit dem letzten Lesen geändert wurde. Hoffe das hilft jemandem.
Ein ähnlicher Ansatz wird in Log4J verwendet
FileWatchdog
.quelle
Sie können Dateiänderungen mit einem FileReader abhören. Bitte sehen Sie das Beispiel unten
quelle
Wenn Sie bereit sind, sich von etwas Geld zu trennen, ist JNIWrapper eine nützliche Bibliothek mit einem Winpack. Sie können Dateisystemereignisse für bestimmte Dateien abrufen. Leider nur Windows.
Siehe https://www.teamdev.com/jniwrapper .
Andernfalls ist der Rückgriff auf nativen Code nicht immer schlecht, insbesondere wenn das beste Angebot ein Abfragemechanismus gegenüber einem nativen Ereignis ist.
Ich habe festgestellt, dass Java-Dateisystemvorgänge auf einigen Computern langsam sein und die Leistung der Anwendung leicht beeinträchtigen können, wenn sie nicht richtig gehandhabt werden.
quelle
Sie können auch die Apache Commons JCI (Java Compiler Interface) in Betracht ziehen. Obwohl sich diese API auf die dynamische Kompilierung von Klassen zu konzentrieren scheint, enthält sie auch Klassen in ihrer API, die Dateiänderungen überwachen.
Beispiel: http://commons.apache.org/jci/usage.html
quelle
Spring Integration bietet einen nützlichen Mechanismus zum Anzeigen von Verzeichnissen und Dateien: http://static.springsource.org/spring-integration/reference/htmlsingle/#files . Ich bin mir ziemlich sicher, dass es plattformübergreifend ist (ich habe es unter Mac, Linux und Windows verwendet).
quelle
Es gibt eine kommerzielle Cross-Desktop-Bibliothek für Dateien und Ordner namens JxFileWatcher. Es kann hier heruntergeladen werden: http://www.teamdev.com/jxfilewatcher/
Sie können es auch online in Aktion sehen: http://www.teamdev.com/jxfilewatcher/onlinedemo/
quelle
Das Abrufen der zuletzt geänderten Dateieigenschaft ist jedoch eine einfache, aber effektive Lösung. Definieren Sie einfach eine Klasse, die my erweitert,
FileChangedWatcher
und implementieren Sie dieonModified()
Methode:quelle
Ähnlich wie bei den anderen Antworten habe ich Folgendes mit File, Timer und TimerTask gemacht, damit dies in festgelegten Intervallen als Hintergrund-Thread-Abfrage ausgeführt wird.
quelle