Je souhaite être averti lorsqu'un fichier a été modifié dans le système de fichiers. Je n'ai rien trouvé d'autre qu'un fil qui interroge la propriété lastModified File et cette solution n'est clairement pas optimale.
Au niveau le plus bas, le seul moyen de modéliser cet utilitaire consiste à interroger les répertoires sur un répertoire et à surveiller 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 tels que Tomcat et d'autres disposent d'une fonctionnalité de chargement automatique dans laquelle, dès que le descripteur de déploiement change ou que la classe de servlet change, le redémarrage de l'application.
Vous pouvez utiliser les bibliothèques à partir de tels serveurs car la plus grande partie du code de Tomcat est réutilisable et opensource.
J'ai déjà écrit un moniteur de fichier journal et j'ai constaté que l'impact sur les performances du système de l'interrogation des attributs d'un fichier unique, plusieurs fois par seconde, était en réalité très faible.
Java 7, dans le cadre de NIO.2, a ajouté le API WatchService
L'API WatchService est conçue pour les applications qui doivent être informées des événements de modification de fichier.
J'utilise l'API VFS d'Apache Commons, voici un exemple de la façon de surveiller un fichier sans trop d'impact sur les performances:
Java commons-io a un FileAlterationObserver . il effectue une interrogation en combinaison avec un FileAlterationMonitor. Similaire à 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 Java Fichier à la place de la couche d’abstraction VFS.
J'exécute cet extrait de code chaque fois que je lis le fichier de propriétés, et que je ne le lis réellement que s'il a été modifié depuis la dernière fois que je l'ai lu. J'espère que ça 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
.
"More NIO features" comporte des fonctionnalités de surveillance de fichiers, dont l'implémentation dépend du système d'exploitation sous-jacent. Devrait être en JDK7.
Vous pouvez écouter les modifications de fichier à 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 avec de l'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, fenêtres uniquement.
Voir https://www.teamdev.com/jniwrapper .
Sinon, le recours au code natif n’est pas toujours une mauvaise chose, en particulier lorsque le meilleur des mécanismes proposés est un mécanisme de sondage par rapport à un événement natif.
J'ai remarqué que Java), les opérations du système de fichiers peuvent être lentes sur certains ordinateurs et peuvent facilement affecter les performances de l'application si elles ne sont pas gérées correctement.
Interroger la dernière propriété de fichier modifiée est une solution simple mais efficace. Il suffit de définir une classe qui étend mon FileChangedWatcher
et de mettre en œuvre la méthode onModified()
:
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();
}
JxFileWatcher est une bibliothèque commerciale interservices pour les fichiers et les dossiers surveillés. Il peut être téléchargé à partir d’ici: http://www.teamdev.com/jxfilewatcher/
Vous pouvez aussi le voir en action en ligne: http://www.teamdev.com/jxfilewatcher/onlinedemo/
Spring Integration fournit un mécanisme de Nice pour surveiller les répertoires et les fichiers: http://static.springsource.org/spring-integration/reference/htmlsingle/#files . Je suis presque sûr que c'est multi-plateforme (je l'ai utilisé sur mac, linux et windows).
Vous pouvez également considérer Apache Commons JCI (Java Compiler Interface). Bien que cette API semble se concentrer sur la compilation dynamique de classes, elle inclut également des classes dans son API qui surveillent les modifications de fichiers.
Semblable aux autres réponses, voici comment je l'ai fait en utilisant File, Timer et TimerTask pour laisser cette tâche s'exécuter en tant que scrutation de thread en 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);
}
}
}