Java'da dosya değiştirilen dinleyici


104

Dosya sisteminde bir dosya değiştirildiğinde bilgilendirilmek istiyorum. LastModified File özelliğini sorgulayan bir iş parçacığından başka bir şey bulamadım ve açıkça bu çözüm optimal değil.


Tüm yanıtlar için teşekkürler. İhtiyaçlarım küçük olduğundan (yalnızca web uygulamamda değiştirilmiş bir özellik dosyasını yeniden yüklemem gerekiyor ... esas olarak tüm web uygulamasını yeniden başlatmak biraz yavaş olduğu için), anket modeline bağlı kalacağım. En azından artık bu davalar için basit bir çözüm olmadığını biliyorum.
cheng81

14
Sadece bir not. Bu sorunu çözdüğümüzde, büyük dosyaların yavaş gelme eğiliminde olduğunu ve yoklama mekanizmasının genellikle tamamen yazılmadan önce yeni veya değiştirilmiş bir dosya keşfettiğini gördük. Bunu çözmek için 'iki ısırık' çözümü benimsendi. Anketçi bir dosyanın değiştiğini fark etti, ancak sisteme iki ankette aynı görünene kadar yeni / değiştirilmiş bir dosya bildirmedi: yani stabilize oldu. Birçok kötü dosya hatasını düzeltti.
Steve Powell

1
Bir kenara, Tomcat büyük WAR dosyalarını uzak kaynaklardan webapps klasörüne bırakırken bu sorunu yaşıyor ve bunu uzun süredir yapıyor.
John Rix

Yanıtlar:


21

Düşük düzeyde, bu yardımcı programı modellemenin tek yolu, bir dizinde bir iş parçacığı sorgulaması yapmak ve dosyanın özniteliklerine bir göz atmaktır. Ancak, böyle bir yardımcı program için bir bağdaştırıcı geliştirmek için desenleri kullanabilirsiniz.

Örneğin, Tomcat ve diğerleri gibi j2ee uygulama sunucuları, dağıtım tanımlayıcısı değişir veya sunucu uygulaması sınıfı değişir değişmez uygulamanın yeniden başlatıldığı otomatik yükleme özelliğine sahiptir.

Tomcat kodunun çoğu yeniden kullanılabilir ve açık kaynaklı olduğu için bu tür sunuculardaki kitaplıkları kullanabilirsiniz.


59
Bu artık Java 7'de geçerli değil: artık bunun için işletim sisteminin bildirim hizmetlerine bağlanabilen bir API var: blogs.oracle.com/thejavatutorials/entry/…
Arnout Engelen

Bu API oldukça yetersizdir, Linux'ta dosya kapatma olayları için bildirim sağlamaz. Bu nedenle, basit bir durumda, bir dosya kapatıldığında, başka bir dizine kopyalamak işe yaramaz.
binarytemple_picsolve

117

Daha önce bir günlük dosyası izleyicisi yazdım ve tek bir dosyanın özniteliklerini saniyede birkaç kez yoklamanın sistem performansı üzerindeki etkisinin aslında çok küçük olduğunu gördüm.

Java 7, NIO.2 parçası eklemiştir olarak WatchService API

WatchService API, dosya değişikliği olayları hakkında bilgilendirilmesi gereken uygulamalar için tasarlanmıştır.


10
Örnekleri izleme dizini olarak görüyorum, peki ya tek bir dosya?
Arşimet Trajano

@ArchimedesTrajano API, bir dizindeki bir dosya değiştiğinde sizi uyarır. Tetiklenen olay, değişen dosyanın adını içerir. Böylece belirli bir dosya veya dosyalar için olayları işleyebilir ve diğerlerini göz ardı edebilirsiniz.
Michael


39

Apache Commons'ın VFS API'sini kullanıyorum, işte performansı çok fazla etkilemeden bir dosyanın nasıl izleneceğine dair bir örnek:

DefaultFileMonitor


27

Denilen bir lib vardır jnotify sarar olduğunu Inotify linux üzerinde ve aynı zamanda pencere desteği vardır. Hiç kullanmadım ve ne kadar iyi olduğunu bilmiyorum ama denemeye değer diyorum.


1
Mükemmel çalışıyor ve kullanımı çok basit. Yıllardır inotify kullanıyorum. Hızlı, kararlı ve güvenilir
oᴉɹǝɥɔ

8

Java commons- io'nun bir FileAlterationObserver'ı vardır . FileAlterationMonitor ile birlikte yoklama yapar. Commons VFS'ye benzer. Avantajı, çok daha az bağımlılığa sahip olmasıdır.

düzenleme: Daha az bağımlılık doğru değildir, bunlar VFS için isteğe bağlıdır. Ancak VFS soyutlama katmanı yerine java Dosyası kullanır.


4

"Daha fazla NIO özelliği", uygulama temeldeki işletim sistemine bağlı olarak dosya izleme işlevine sahiptir. JDK7'de olmalıdır.


Daha spesifik olabilir misiniz veya belgelere bir bağlantı gönderebilir misiniz? Bu konuda bir şey bulamıyor gibi görünüyor ...
Luciano

Paket gibi görünüyor java.nio.file. Bir eğiticiye bakın .
David L.

4

Özellikler dosyasını her okumaya gittiğimde bu kod parçacığını çalıştırıyorum, sadece dosyayı son okuduğumdan beri değiştirilmişse gerçekten okuyorum. Umarım bu birine yardımcı olur.

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'de benzer bir yaklaşım kullanılmaktadır FileWatchdog.


2

Bir FileReader kullanarak dosya değişikliklerini dinleyebilirsiniz. Plz aşağıdaki örneğe bakın

// 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

Biraz parayla ayrılmak istiyorsanız, JNIWrapper bir Winpack ile kullanışlı bir kitaplıktır, belirli dosyalarda dosya sistemi olaylarını alabilirsiniz. Ne yazık ki sadece pencereler.

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

Aksi takdirde, yerel koda başvurmak her zaman kötü bir şey değildir, özellikle sunulan en iyi şey yerel bir olaya karşı bir oylama mekanizması olduğunda.

Java dosya sistemi işlemlerinin bazı bilgisayarlarda yavaş olabileceğini ve iyi işlenmezse uygulamanın performansını kolayca etkileyebileceğini fark ettim.





1

Yine de son değiştirilen dosya özelliğini sorgulamak basit ama etkili bir çözümdür. Sadece my'ı genişleten bir sınıf tanımlayın FileChangedWatcherve onModified()yöntemi uygulayın:

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

Diğer yanıtlara benzer şekilde, File, Timer ve TimerTask kullanarak bunun belirli aralıklarla arka plan iş parçacığı yoklaması olarak çalışmasına izin vermek için bunu nasıl yaptım.

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

  }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.