Je souhaite être averti lorsqu'un fichier a été modifié dans le système de fichiers. Je n'ai trouvé rien d'autre qu'un fil qui interroge la propriété lastModified File et clairement cette solution n'est pas optimale.
Je souhaite être averti lorsqu'un fichier a été modifié dans le système de fichiers. Je n'ai trouvé rien d'autre qu'un fil qui interroge la propriété lastModified File et clairement cette solution n'est pas optimale.
Réponses:
Au bas niveau, la seule façon de modéliser cet utilitaire est d'avoir un thread qui interroge un répertoire et surveille les attributs du fichier. Mais vous pouvez utiliser des modèles pour développer un adaptateur pour un tel utilitaire.
Par exemple, les serveurs d'applications j2ee comme Tomcat et d'autres ont une fonction de chargement automatique dans laquelle dès que le descripteur de déploiement change ou que la classe de servlet change, l'application redémarre.
Vous pouvez utiliser les bibliothèques de ces serveurs car la plupart du code de tomcat est réutilisable et open source.
J'ai déjà écrit un moniteur de fichier journal et j'ai trouvé que l'impact sur les performances du système de l'interrogation des attributs d'un seul fichier, quelques fois par seconde, est en fait très faible.
Java 7, dans le cadre de NIO.2 a ajouté l' API WatchService
L'API WatchService est conçue pour les applications qui doivent être notifiées des événements de modification de fichier.
J'utilise l'API VFS d'Apache Commons, voici un exemple de comment surveiller un fichier sans grand impact sur les performances:
Il existe une bibliothèque appelée jnotify qui encapsule inotify sur Linux et prend également en charge Windows. Je ne l'ai jamais utilisé et je ne sais pas à quel point c'est bon, mais ça vaut le coup d'essayer je dirais.
Java commons-io a un FileAlterationObserver . il interroge en combinaison avec un FileAlterationMonitor. Similaire au VFS commun. L'avantage est qu'il a beaucoup moins de dépendances.
edit: Moins de dépendances n'est pas vrai, elles sont facultatives pour VFS. Mais il utilise un fichier java au lieu de la couche d'abstraction VFS.
«Plus de fonctionnalités NIO» a une fonctionnalité de surveillance des fichiers, avec une implémentation dépendante du système d'exploitation sous-jacent. Doit être dans JDK7.
J'exécute cet extrait de code chaque fois que je vais lire le fichier de propriétés, ne lisant réellement le fichier que s'il a été modifié depuis la dernière fois que je l'ai lu. J'espère que cela aide quelqu'un.
private long timeStamp;
private File file;
private boolean isFileUpdated( File file ) {
this.file = file;
this.timeStamp = file.lastModified();
if( this.timeStamp != timeStamp ) {
this.timeStamp = timeStamp;
//Yes, file is updated
return true;
}
//No, file is not updated
return false;
}
Une approche similaire est utilisée dans Log4J FileWatchdog
.
Vous pouvez écouter les modifications de fichiers à l'aide d'un FileReader. Plz voir l'exemple ci-dessous
// File content change listener
private String fname;
private Object lck = new Object();
...
public void run()
{
try
{
BufferedReader br = new BufferedReader( new FileReader( fname ) );
String s;
StringBuilder buf = new StringBuilder();
while( true )
{
s = br.readLine();
if( s == null )
{
synchronized( lck )
{
lck.wait( 500 );
}
}
else
{
System.out.println( "s = " + s );
}
}
}
catch( Exception e )
{
e.printStackTrace();
}
}
Si vous êtes prêt à vous séparer d'un peu d'argent, JNIWrapper est une bibliothèque utile avec un Winpack, vous pourrez obtenir des événements du système de fichiers sur certains fichiers. Malheureusement Windows uniquement.
Voir https://www.teamdev.com/jniwrapper .
Sinon, le recours au code natif n'est pas toujours une mauvaise chose surtout quand le meilleur proposé est un mécanisme d'interrogation par rapport à un événement natif.
J'ai remarqué que les opérations du système de fichiers Java peuvent être lentes sur certains ordinateurs et peuvent facilement affecter les performances de l'application si elles ne sont pas bien gérées.
Vous pouvez également envisager la JCI Apache Commons (Java Compiler Interface). Bien que cette API semble être axée sur la compilation dynamique de classes, elle inclut également des classes dans son API qui surveille les modifications de fichiers.
Spring Integration fournit un bon mécanisme pour regarder les répertoires et les fichiers: http://static.springsource.org/spring-integration/reference/htmlsingle/#files . À peu près sûr que c'est multiplateforme (je l'ai utilisé sur mac, Linux et Windows).
Il existe une bibliothèque commerciale cross-desktop pour les fichiers et dossiers à surveiller appelée JxFileWatcher. Il peut être téléchargé ici: http://www.teamdev.com/jxfilewatcher/
Vous pouvez également le voir en action en ligne: http://www.teamdev.com/jxfilewatcher/onlinedemo/
L'interrogation de la dernière propriété de fichier modifiée est cependant une solution simple mais efficace. Définissez simplement une classe étendant my FileChangedWatcher
et implémentez la onModified()
méthode:
import java.io.File;
public abstract class FileChangedWatcher
{
private File file;
public FileChangedWatcher(String filePath)
{
file = new File(filePath);
}
public void watch() throws InterruptedException
{
long currentModifiedDate = file.lastModified();
while (true)
{
long newModifiedDate = file.lastModified();
if (newModifiedDate != currentModifiedDate)
{
currentModifiedDate = newModifiedDate;
onModified();
}
Thread.sleep(100);
}
}
public String getFilePath()
{
return file.getAbsolutePath();
}
protected abstract void onModified();
}
Semblable aux autres réponses, voici comment je l'ai fait en utilisant File, Timer et TimerTask pour laisser cela fonctionner en tant qu'interrogation de thread d'arrière-plan à des intervalles définis.
import java.io.File;
import java.util.Timer;
import java.util.TimerTask;
public class FileModifiedWatcher
{
private static File file;
private static int pollingInterval;
private static Timer fileWatcher;
private static long lastReadTimeStamp = 0L;
public static boolean init(String _file, int _pollingInterval)
{
file = new File(_file);
pollingInterval = _pollingInterval; // In seconds
watchFile();
return true;
}
private static void watchFile()
{
if ( null == fileWatcher )
{
System.out.println("START");
fileWatcher = new Timer();
fileWatcher.scheduleAtFixedRate(new TimerTask()
{
@Override
public void run()
{
if ( file.lastModified() > lastReadTimeStamp )
{
System.out.println("File Modified");
}
lastReadTimeStamp = System.currentTimeMillis();
}
}, 0, 1000 * pollingInterval);
}
}
}