Domanda

Vorrei essere avvisato quando un file è stato modificato nel file system. Non ho trovato altro che un thread che esegue il polling della proprietà lastModified File e chiaramente questa soluzione non è ottimale.

È stato utile?

Soluzione

A basso livello l'unico modo per modellare questa utility è avere un thread polling su una directory e tenere d'occhio gli attributi del file. Ma puoi usare i pattern per sviluppare un adattatore per tale utility.

Ad esempio i server applicazioni j2ee come Tomcat e altri hanno una funzione di caricamento automatico in cui non appena il descrittore di distribuzione cambia o la classe servlet cambia il riavvio dell'applicazione.

È possibile utilizzare le librerie di tali server poiché la maggior parte del codice di Tomcat è riutilizzabile e opensource.

Altri suggerimenti

Ho già scritto un monitor per i file di registro e ho scoperto che l'impatto sulle prestazioni del sistema del polling degli attributi di un singolo file, alcune volte al secondo, è in realtà molto ridotto.

Java 7, come parte di NIO.2 ha aggiunto API WatchService

  

L'API WatchService è progettata per le applicazioni che devono essere informate sugli eventi di modifica dei file.

Uso l'API VFS di Apache Commons, ecco un esempio di come monitorare un file senza influire molto sulle prestazioni:

DefaultFileMonitor

Esiste una lib chiamata jnotify che avvolge inotify su Linux e ha anche il supporto per Windows. Non l'ho mai usato e non so quanto sia bello, ma vale la pena provare, direi.

Java commons-io ha un FileAlterationObserver . esegue il polling in combinazione con un FileAlterationMonitor. Simile a VFS comuni. Il vantaggio è che ha molte meno dipendenze.

modifica: meno dipendenze non sono vere, sono opzionali per VFS. Ma utilizza java File invece del livello di astrazione VFS.

" Altre funzioni NIO " ha la funzionalità di controllo dei file, con un'implementazione che dipende dal sistema operativo sottostante. Dovrebbe essere in JDK7.

Eseguo questo frammento di codice ogni volta che vado a leggere il file delle proprietà, leggendo effettivamente il file solo se è stato modificato dall'ultima volta che l'ho letto. Spero che questo aiuti qualcuno.

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;
}

Approccio simile viene utilizzato in Log4J FileWatchdog .

Puoi ascoltare le modifiche ai file usando un FileReader. Per favore vedi l'esempio qui sotto

// 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();
    }
}

Se sei disposto a separarti, JNIWrapper è una libreria utile con un Winpack, sarai in grado di ottenere eventi del file system su determinati file. Sfortunatamente solo per Windows.

Vedi https://www.teamdev.com/jniwrapper .

Altrimenti, ricorrere al codice nativo non è sempre una brutta cosa, specialmente quando la migliore offerta è un meccanismo di polling rispetto a un evento nativo.

Ho notato che le operazioni del file system Java possono essere lente su alcuni computer e possono facilmente influire sulle prestazioni dell'applicazione se non gestite bene.

Puoi anche prendere in considerazione il JCI (Java Compiler Interface) di Apache Commons. Anche se questa API sembra essere focalizzata sulla compilazione dinamica di classi, include anche classi nella sua API che monitora le modifiche ai file.

Esempio: http://commons.apache.org/jci/usage.html

Spring Integration fornisce un meccanismo utile per guardare directory e file: http: / /static.springsource.org/spring-integration/reference/htmlsingle/#files . Abbastanza sicuro che sia multipiattaforma (l'ho usato su Mac, Linux e Windows).

Esiste una libreria commerciale cross-desktop per la visione di file e cartelle chiamata JxFileWatcher. Può essere scaricato da qui: http://www.teamdev.com/jxfilewatcher/

Inoltre puoi vederlo in azione online:   http://www.teamdev.com/jxfilewatcher/onlinedemo/

Il polling dell'ultima proprietà del file modificato è una soluzione semplice ma efficace. Basta definire una classe che estende il mio FileChangedWatcher e implementare il metodo 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();
}

Simile alle altre risposte, ecco come l'ho fatto usando File, Timer e TimerTask per lasciarlo funzionare come polling di thread in background a intervalli prestabiliti.

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);
    }

  }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top