Я хочу получать уведомление об изменении файла в файловой системе. Я не нашел ничего, кроме потока, который опрашивает свойство lastModified File, и ясно, что это решение не оптимально.
Я хочу получать уведомление об изменении файла в файловой системе. Я не нашел ничего, кроме потока, который опрашивает свойство lastModified File, и ясно, что это решение не оптимально.
Ответы:
На низком уровне единственный способ смоделировать эту утилиту - это опрос потока в каталоге и наблюдение за атрибутами файла. Но вы можете использовать шаблоны для разработки адаптера для такой утилиты.
Например, серверы приложений j2ee, такие как Tomcat и другие, имеют функцию автоматической загрузки, при которой, как только изменяется дескриптор развертывания или класс сервлета, приложение перезапускается.
Вы можете использовать библиотеки с таких серверов, поскольку большая часть кода tomcat является многоразовым и имеет открытый исходный код.
Раньше я писал монитор файлов журнала и обнаружил, что влияние на производительность системы опроса атрибутов одного файла несколько раз в секунду на самом деле очень мало.
Java 7, как часть NIO.2, добавила WatchService API
WatchService API разработан для приложений, которым необходимо получать уведомления о событиях изменения файлов.
Я использую VFS API от Apache Commons, вот пример того, как отслеживать файл без особого влияния на производительность:
Существует библиотека jnotify, которая обертывает inotify в Linux, а также поддерживает Windows. Никогда не использовал, и я не знаю, насколько он хорош, но я бы сказал, что попробовать стоит.
В Java commons-io есть FileAlterationObserver . он выполняет опрос в сочетании с FileAlterationMonitor. Аналогично общему VFS. Преимущество в том, что у него гораздо меньше зависимостей.
edit: Меньше зависимостей неверно, они не являются обязательными для VFS. Но он использует файл java вместо уровня абстракции VFS.
«Дополнительные функции NIO» включают функцию отслеживания файлов, реализация которой зависит от базовой ОС. Должен быть в JDK7.
Я запускаю этот фрагмент кода каждый раз, когда иду читать файл свойств, фактически читая файл только в том случае, если он был изменен с момента последнего чтения. Надеюсь, это кому-то поможет.
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;
}
Аналогичный подход используется в Log4J FileWatchdog
.
Вы можете прослушивать изменения файлов с помощью FileReader. Пожалуйста, посмотрите пример ниже
// 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();
}
}
Если вы готовы расстаться с деньгами, JNIWrapper - полезная библиотека с Winpack, вы сможете получать события файловой системы для определенных файлов. К сожалению только окна.
См. Https://www.teamdev.com/jniwrapper .
В противном случае обращение к собственному коду не всегда плохо, особенно когда лучшее из предлагаемых - это механизм опроса, а не собственное событие.
Я заметил, что операции файловой системы Java могут быть медленными на некоторых компьютерах и могут легко повлиять на производительность приложения, если с ними не справиться.
Вы также можете рассмотреть Apache Commons JCI (интерфейс компилятора Java). Хотя этот API, похоже, ориентирован на динамическую компиляцию классов, он также включает классы в свой API, который отслеживает изменения файлов.
Spring Integration предоставляет удобный механизм для просмотра каталогов и файлов: http://static.springsource.org/spring-integration/reference/htmlsingle/#files . Уверен, что это кроссплатформенный (я использовал его на Mac, Linux и Windows).
Существует коммерческая кросс-десктопная библиотека для просмотра файлов и папок под названием JxFileWatcher. Его можно скачать здесь: http://www.teamdev.com/jxfilewatcher/
Также вы можете увидеть это в действии онлайн: http://www.teamdev.com/jxfilewatcher/onlinedemo/
Однако опрос последнего измененного свойства файла - простое, но эффективное решение. Просто определите класс, расширяющий мой, FileChangedWatcher
и реализуйте 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();
}
Как и в других ответах, вот как я это сделал, используя File, Timer и TimerTask, чтобы позволить этому запускать в качестве фонового опроса потока через заданные интервалы.
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);
}
}
}