Файл змінив слухача на Java


104

Мені хотілося б отримати повідомлення, коли файл змінився у файловій системі. Я не знайшов нічого, крім потоку, який опитує властивість lastModified File, і явно це рішення не є оптимальним.


Дякую за всі відповіді. Оскільки мої потреби невеликі (мені потрібно лише перезавантажити файл властивостей, змінений у моєму веб-додатку. Головним чином, тому що перезапуск всього веб-сайту начебто повільний), я буду дотримуватися моделі опитування. Принаймні зараз я знаю, що не існує простого рішення для тез.
cheng81

14
Просто записка. Коли ми вирішили цю проблему, перш ніж ми виявили, що великі файли, як правило, надходять повільно, і механізм опитування часто виявляв новий або змінений файл до того, як він був повністю записаний. Для вирішення цього рішення було прийнято рішення "двох укусів". Поллер помітив, що файл змінився, але не повідомив систему про новий / змінений файл, поки він не виглядав однаково для двох опитувань: тобто стабілізувався. Вилікували багато помилок помилок.
Стів Пауелл

1
Зауваження, Tomcat страждає від цієї проблеми, коли викидає великі файли WAR у папку webapps з віддалених джерел і робить це вже давно.
Джон Рікс

Відповіді:


21

На низькому рівні єдиний спосіб моделювання цієї утиліти - це тематика опитування каталогів та збереження уваги за атрибутами файлу. Але ви можете використовувати шаблони для розробки адаптера для такої утиліти.

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

Ви можете використовувати бібліотеки з таких серверів, оскільки більшість кодів tomcat є багаторазовими і відкритими.


59
Це вже не відповідає дійсності Java 7: тепер для цього існує API, який може підключитися до служб сповіщень ОС: blogs.oracle.com/thejavatutorials/entry/…
Енгелен,

Цей API вкрай неадекватний, він не забезпечує сповіщення про події закриття файлів в Linux. Отже, враховуючи простий випадок, коли файл закритий, скопіювати його в інший каталог не працює.
binarytemple_picsolve

117

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

Java 7 як частина NIO.2 додала API WatchService

API WatchService призначений для додатків, яким потрібно повідомити про події зміни файлів.


10
Я бачу приклади як перегляд каталогів, але як бути з окремим файлом?
Архімед Траяно

@ArchimedesTrajano API повідомляє вас про зміну файлу в каталозі. Подія, що запускається, включає ім'я файла, який змінився. Таким чином, ви можете обробляти події для певного файлу чи файлів та ігнорувати інші.
Майкл


39

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

DefaultFileMonitor


27

Існує ліб під назвою jnotify, який обгортає ініціативу на Linux і також підтримує Windows. Ніколи не використовував його, і я не знаю, наскільки це добре, але варто спробувати.


1
Це ідеально і дуже просто у використанні. Я багато років використовую inotify. Це швидко, стабільно та надійно
1313

8

У Java commons-io є FileAlterationObserver . це опитування в поєднанні з FileAlterationMonitor. Схожий на commons VFS. Перевага в тому, що він має набагато менше залежностей.

редагувати: менше залежностей не відповідає дійсності, вони є необов'язковими для VFS. Але він використовує файл Java, а не шар абстракції VFS.


4

"Більше функцій NIO" має функцію перегляду файлів, реалізація залежить від основної ОС. Повинно бути в JDK7.


Чи можете ви бути більш конкретними або опублікувати посилання на документацію? Здається, на цьому нічого не можна знайти ...
Luciano

Здається, це пакет java.nio.file. Дивіться підручник .
Девід Л.

4

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

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.


2

Ви можете прослуховувати зміни файлів за допомогою FileReader. Plz див. Приклад нижче

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

2

Якщо ви готові розлучитися з деякими грошима, JNIWrapper - це корисна бібліотека з Winpack, ви зможете отримати події файлової системи на певних файлах. На жаль, тільки вікна.

Дивіться https://www.teamdev.com/jniwrapper .

В іншому випадку вдаватися до нативного коду не завжди є поганою справою, особливо коли найкраща пропозиція - це механізм опитування, як проти рідної події.

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


1

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

Приклад: http://commons.apache.org/jci/usage.html




1

Опитування останньої модифікованої властивості файлу є простим, але ефективним рішенням. Просто визначте клас, який розширює мій, 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();
}

0

Подібно до інших відповідей, ось як я це зробив за допомогою файлу, таймера та 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);
    }

  }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.