Arquivo alterado ouvinte em Java

Eu gostaria de ser notificado quando um arquivo foi alterado no sistema de arquivos. Eu encontrei nada, mas um segmento que pesquisa a propriedade LastModified File e claramente esta solução não é ideal.

   

    No nível baixo, a única maneira de modelar esse utilitário é fazer uma pesquisa de thread em um diretório e manter uma observação sobre os atributos do arquivo. Mas você pode usar padrões para desenvolver um adaptador para tal utilitário.

    Por exemplo, os servidores de aplicativos j2ee, como o Tomcat e outros, têm um recurso de carregamento automático no qual, assim que as alterações do descritor de implementação ou a class do servlet são alteradas, o aplicativo é reiniciado.

    Você pode usar as bibliotecas de tais servidores como a maioria do código do tomcat é reutilizável e opensource.

    Eu escrevi um monitor de arquivo de log antes, e descobri que o impacto no desempenho do sistema de pesquisar os atributos de um único arquivo, algumas vezes por segundo, é realmente muito pequeno.

    O Java 7, como parte da NIO.2, adicionou a API WatchService

    A API WatchService é projetada para aplicativos que precisam ser notificados sobre events de alteração de arquivo.

    Eu uso a API VFS do Apache Commons, aqui está um exemplo de como monitorar um arquivo sem muito impacto no desempenho:

    DefaultFileMonitor

    Existe um lib chamado jnotify que envolve inotify no linux e também tem suporte para windows. Nunca usei e não sei como é bom, mas vale a pena tentar, eu diria.

    Java commons-io tem um FileAlterationObserver . ele faz polling em combinação com um FileAlterationMonitor. Semelhante ao commons VFS. O advantag é que tem muito menos dependencies.

    Editar: Menos dependencies não são verdadeiras, elas são opcionais para o VFS. Mas usa o arquivo java em vez da camada de abstração do VFS.

    “Mais resources do NIO” tem a funcionalidade de monitoração de arquivos, com a implementação dependente do sistema operacional subjacente. Deve estar no JDK7.

    Eu corro este trecho de código toda vez que vou ler o arquivo de propriedades, só lendo o arquivo se ele foi modificado desde a última vez que o li. Espero que isso ajude alguém.

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

    Uma abordagem semelhante é usada no Log4J FileWatchdog .

    Se você está disposto a compartilhar com algum dinheiro JNIWrapper é útil biblioteca com um Winpack, você será capaz de obter events do sistema de arquivos em determinados arquivos. Infelizmente apenas janelas.

    http://www.teamdev.com/jniwrapper/index.jsf

    Caso contrário, recorrer ao código nativo nem sempre é uma coisa ruim, especialmente quando a melhor oferta é um mecanismo de pesquisa contra um evento nativo.

    Percebi que as operações do sistema de arquivos java podem ser lentas em alguns computadores e podem afetar facilmente o desempenho dos aplicativos, se não forem bem tratadas.

    Você também pode considerar o Apache Commons JCI (Java Compiler Interface). Embora essa API pareça estar focada na compilation dinâmica de classs, ela também inclui classs em sua API que monitora alterações de arquivos.

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

    O Spring Integration fornece um bom mecanismo para assistir Diretórios e arquivos: http://static.springsource.org/spring-integration/reference/htmlsingle/#files . Tenho certeza que é plataforma cruzada (eu usei no mac, linux e windows).

    Você pode ouvir as alterações de arquivo usando um FileReader. Plz veja o exemplo abaixo

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

    Existe uma biblioteca cross-desktop comercial para arquivos e pastas assistindo chamado JxFileWatcher. Pode ser baixado aqui: http://www.teamdev.com/jxfilewatcher/

    Também você pode vê-lo em ação online: http://www.teamdev.com/jxfilewatcher/onlinedemo/

    Semelhante às outras respostas, aqui está como eu fiz isso usando File, Timer e TimerTask para permitir que isso seja executado como uma pesquisa de thread em segundo plano em intervalos definidos.

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

    A pesquisa da última propriedade de arquivo modificada é uma solução simples, porém eficaz. Apenas defina uma class estendendo meu FileChangedWatcher e implemente o método 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(); }