Вопрос

Я хотел бы получать уведомления, когда файл был изменен в файловой системе.Я не нашел ничего, кроме потока, который опрашивает свойство LastModified File, и очевидно, что это решение не является оптимальным.

Это было полезно?

Решение

На низком уровне единственный способ смоделировать эту утилиту — это опросить поток каталога и отслеживать атрибуты файла.Но вы можете использовать шаблоны для разработки адаптера для такой утилиты.

Например, серверы приложений j2ee, такие как Tomcat и другие, имеют функцию автоматической загрузки, при которой, как только изменяется дескриптор развертывания или изменяется класс сервлета, приложение перезапускается.

Вы можете использовать библиотеки с таких серверов, поскольку большая часть кода Tomcat пригодна для повторного использования и имеет открытый исходный код.

Другие советы

Раньше я писал монитор файлов журналов и обнаружил, что влияние на производительность системы опроса атрибутов одного файла несколько раз в секунду на самом деле очень незначительно.

В Java 7, как часть NIO.2, добавлена ​​возможность API службы часов

API WatchService предназначен для приложений, которым необходимо получать уведомления о событиях изменения файлов.

Я использую API VFS от Apache Commons, вот пример того, как отслеживать файл без особого влияния на производительность:

Дефолтфилемонитор

Существует библиотека под названием jnotify это оборачивает уведомлять на Linux, а также поддерживает Windows.Никогда им не пользовался и не знаю, насколько он хорош, но попробовать стоит, я бы сказал.

Java commons-io имеет FileAlterationObserver.он выполняет опрос в сочетании с FileAlterationMonitor.Аналогично Commons VFS.Преимущество в том, что у него гораздо меньше зависимостей.

редактировать:Меньше зависимостей неверно, они не являются обязательными для 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, вы сможете получать события файловой системы для определенных файлов.К сожалению, только Windows.

Видеть https://www.teamdev.com/jniwrapper.

В противном случае обращение к собственному коду не всегда плохо, особенно когда лучшее, что можно предложить, — это механизм опроса, а не собственное событие.

Я заметил, что операции файловой системы Java на некоторых компьютерах могут быть медленными и могут легко повлиять на производительность приложения, если с ними не справиться должным образом.

Вы также можете рассмотреть Apache Commons JCI (интерфейс компилятора Java).Хотя этот API, похоже, ориентирован на динамическую компиляцию классов, он также включает в свой API классы, которые отслеживают изменения файлов.

Пример:http://commons.apache.org/jci/usage.html

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

  }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top