Gostaria de ser notificado quando um arquivo for alterado no sistema de arquivos. Não encontrei nada além de um thread que pesquisa a propriedade lastModified File e, claramente, essa solução não é a ideal.
Gostaria de ser notificado quando um arquivo for alterado no sistema de arquivos. Não encontrei nada além de um thread que pesquisa a propriedade lastModified File e, claramente, essa solução não é a ideal.
Respostas:
No nível mais baixo, a única maneira de modelar esse utilitário é ter uma pesquisa de encadeamento em um diretório e observar os atributos do arquivo. Mas você pode usar padrões para desenvolver um adaptador para esse utilitário.
Por exemplo, servidores de aplicativos j2ee, como Tomcat e outros, têm um recurso de carregamento automático em que, assim que o descritor de implementação muda ou a classe de servlet muda, o aplicativo é reiniciado.
Você pode usar as bibliotecas de servidores como a maioria do código do tomcat é reutilizável e de código aberto.
Já escrevi um monitor de arquivo de log antes e descobri que o impacto sobre o desempenho do sistema de pesquisar os atributos de um único arquivo, algumas vezes por segundo, é realmente muito pequeno.
Java 7, como parte do NIO.2, adicionou a API WatchService
A API WatchService foi projetada para aplicativos que precisam ser notificados sobre 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:
Java commons-io tem um FileAlterationObserver . ele faz polling em combinação com um FileAlterationMonitor. Semelhante ao VFS comum. A vantagem é que ele tem muito menos dependências.
editar: Menos dependências não é verdade, são opcionais para VFS. Mas ele usa o arquivo java em vez da camada de abstração VFS.
"Mais recursos NIO" tem funcionalidade de observação de arquivo, com implementação dependente do sistema operacional subjacente. Deve estar em JDK7.
Eu executo esse trecho de código toda vez que vou ler o arquivo de propriedades, apenas 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;
}
Abordagem semelhante é usada no Log4J FileWatchdog
.
Você pode ouvir as alterações do arquivo usando um FileReader. Por favor, 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ê está disposto a gastar algum dinheiro, JNIWrapper é uma biblioteca útil com um Winpack, você poderá obter eventos do sistema de arquivos em certos arquivos. Infelizmente, apenas o Windows.
Veja https://www.teamdev.com/jniwrapper .
Caso contrário, recorrer ao código nativo nem sempre é uma coisa ruim, especialmente quando o melhor em oferta é um mecanismo de votação em oposição a um evento nativo.
Percebi que as operações do sistema de arquivos Java podem ser lentas em alguns computadores e podem facilmente afetar o desempenho do aplicativo se não forem bem gerenciadas.
Você também pode considerar o Apache Commons JCI (Java Compiler Interface). Embora essa API pareça estar focada na compilação dinâmica de classes, ela também inclui classes em sua API que monitora as alterações de arquivo.
O Spring Integration fornece um bom mecanismo para monitorar 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).
Há uma biblioteca comercial entre desktops para monitoramento de arquivos e pastas chamada JxFileWatcher. Ele 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/
No entanto, pesquisar a última propriedade do arquivo modificado é uma solução simples, mas eficaz. Basta definir uma classe estendendo my FileChangedWatcher
e implementar o onModified()
método:
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();
}
Semelhante às outras respostas, aqui está como 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);
}
}
}