Pergunta

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

Foi útil?

Solução

Ao nível baixo a única maneira de modelar esta utilidade é ter um polling linha em um diretório e manter uma vigilância sobre os atributos do arquivo. Mas você pode usar padrões para desenvolver um adaptador para esse utilitário a.

Para servidores de aplicativos exemplo J2EE como Tomcat e outros têm uma característica de carga automático, onde, na maior brevidade mudanças descritor de implementação ou classe servlet muda o aplicativo for reiniciado.

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

Outras dicas

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

Java 7, como parte de NIO.2 acrescentou o WatchService API

A API WatchService é projetado para aplicações que precisam ser notificados sobre os eventos 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

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

commons-io Java tem um FileAlterationObserver . ele faz sondagens em combinação com um FileAlterationMonitor. Semelhante ao Commons VFS. O advantag é que ele tem muito menos dependências.

edit: Menos dependências não é verdade, eles são opcionais para VFS. Mas ele usa java arquivo em vez da camada de abstração de VFS.

"Mais NIO apresenta" tem a funcionalidade de relógio de arquivo, com a implementação depende do sistema operacional subjacente. Deve estar em JDK7.

Eu corro esse trecho de código cada vez que vou para ler o arquivo de propriedades, única realmente ler o arquivo se ele foi modificado desde a última vez que eu 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;
}

abordagem semelhante é usado em Log4J FileWatchdog .

Você pode ouvir as alterações de arquivos 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();
    }
}

Se você estiver disposto a parte com algum dinheiro, JNIWrapper é uma biblioteca útil com um Winpack, você será capaz de obter eventos do sistema de arquivos em certos arquivos. Infelizmente, somente para Windows.

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

Caso contrário, recorrendo a código nativo não é sempre uma coisa ruim, especialmente quando o melhor em oferta é um mecanismo de pesquisa, como a um evento nativo.

Eu tenho notado que as operações do sistema de arquivos Java pode ser lento em alguns computadores e pode facilmente afetar o desempenho do aplicativo se não for bem tratada.

Você também pode considerar o Apache Commons JCI (Java Compiler Interface). Embora esta API parece estar focada na compilação dinâmica das aulas, ele também inclui aulas em sua API que mudanças de arquivos monitores.

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

Spring Integration fornece um mecanismo legal para assistir diretórios e arquivos: http: / /static.springsource.org/spring-integration/reference/htmlsingle/#files . Certeza que é multiplataforma (Eu usei-o no mac, linux e windows).

Há uma biblioteca multi-desktop comercial para arquivos e pastas assistindo chamado JxFileWatcher. Ele pode ser baixado a partir daqui: http://www.teamdev.com/jxfilewatcher/

Além disso, você pode vê-lo em ação on-line: http://www.teamdev.com/jxfilewatcher/onlinedemo/

Polling a última propriedade arquivo modificado é uma solução eficaz, embora simples ainda. Apenas definir uma classe estender minha FileChangedWatcher e implementar 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();
}

Assim como as outras respostas, aqui está como eu fiz isso usando Arquivo, Timer, e TimerTask para deixar esta corrida como um polling discussão de fundo 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);
    }

  }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top