Java에서 파일 변경 리스너


104

파일 시스템에서 파일이 변경되었을 때 알림을 받고 싶습니다. lastModified File 속성을 폴링하는 스레드 만 발견했으며이 솔루션은 최적이 아닙니다.


모든 응답에 감사드립니다. 내 요구 사항이 적기 때문에 (주로 전체 웹 응용 프로그램을 다시 시작하는 것이 다소 느리기 때문에 변경된 속성 파일을 웹 응용 프로그램에서 다시로드하면됩니다.) 설문 조사 모델을 고수 할 것입니다. 적어도 지금은 이러한 경우에 대한 간단한 해결책이 없다는 것을 알고 있습니다.
cheng81

14
메모입니다. 대용량 파일이 느리게 들어오는 경향이 있다는 것을 발견하기 전에이 문제를 해결했을 때 폴링 메커니즘은 종종 완전히 작성되기 전에 새 파일이나 변경된 파일을 발견했습니다. 이를 해결하기 위해 '투 바이트'솔루션이 채택되었습니다. 폴러는 파일이 변경되었음을 알아 차 렸지만 두 개의 폴에 대해 동일하게 보일 때까지 시스템에 새 파일 / 변경된 파일을 알리지 않았습니다. 즉, 안정화되었습니다. 많은 불량 파일 오류를 해결했습니다.
Steve Powell

1
제쳐두고, Tomcat은 원격 소스에서 webapps 폴더로 대용량 WAR 파일을 드롭 할 때 이러한 문제를 겪고 있으며 오랫동안 그렇게 해왔습니다.
John Rix

답변:


21

낮은 수준에서이 유틸리티를 모델링하는 유일한 방법은 디렉터리에서 스레드를 폴링하고 파일의 속성을 감시하는 것입니다. 그러나 패턴을 사용하여 이러한 유틸리티 용 어댑터를 개발할 수 있습니다.

예를 들어 Tomcat 등의 j2ee 애플리케이션 서버에는 배포 설명자가 변경되거나 서블릿 클래스가 변경되는 즉시 애플리케이션이 다시 시작되는 자동로드 기능이 있습니다.

대부분의 tomcat 코드는 재사용 가능하고 오픈 소스이므로 이러한 서버의 라이브러리를 사용할 수 있습니다.


59
이는 더 이상 자바 7의 사실입니다 : 운영 체제의 알림 서비스에 연결할 수 있습니다이에 대한 API가 지금있다 : blogs.oracle.com/thejavatutorials/entry/...이
Arnout Engelen

이 API는 매우 부적절하며 Linux에서 파일 닫기 이벤트에 대한 알림을 제공하지 않습니다. 따라서 간단한 경우 파일이 닫히면 다른 디렉토리로 복사하면 작동하지 않습니다.
binarytemple_picsolve

117

이전에 로그 파일 모니터를 작성했는데, 1 초에 몇 번씩 단일 파일의 속성을 폴링 할 때 시스템 성능에 미치는 영향이 실제로 매우 작다는 것을 발견했습니다.

Java 7, NIO.2의 일부로 WatchService API 가 추가되었습니다.

WatchService API는 파일 변경 이벤트에 대한 알림을 받아야하는 애플리케이션을 위해 설계되었습니다.


10
예제는 감시 디렉토리로 보이지만 개별 파일은 어떻습니까?
Archimedes Trajano

@ArchimedesTrajano API는 디렉토리의 파일이 변경되면 알려줍니다. 트리거되는 이벤트에는 변경된 파일의 이름이 포함됩니다. 따라서 특정 파일에 대한 이벤트를 처리하고 다른 파일을 무시할 수 있습니다.
Michael


39

Apache Commons의 VFS API를 사용합니다. 다음은 성능에 큰 영향을주지 않고 파일을 모니터링하는 방법의 예입니다.

DefaultFileMonitor


27

Linux에서 inotify 를 래핑 하고 Windows도 지원하는 jnotify 라는 lib 가 있습니다. 한번도 사용하지 않았고 얼마나 좋은지 모르겠지만 시도해 볼 가치가 있습니다.


1
완벽하고 사용하기 매우 간단합니다. 나는 수년 동안 inotify를 사용해 왔습니다. 빠르고 안정적이며 신뢰할 수 있습니다
oᴉɹǝɥɔ

8

Java commons-io에는 FileAlterationObserver가 있습니다. FileAlterationMonitor와 결합하여 폴링을 수행합니다. Commons VFS와 유사합니다. 장점은 종속성이 훨씬 적다는 것입니다.

편집 : 더 적은 종속성은 사실이 아니며 VFS의 경우 선택 사항입니다. 그러나 VFS 추상화 계층 대신 Java 파일을 사용합니다.


4

"더 많은 NIO 기능"에는 기본 OS에 따라 구현되는 파일 감시 기능이 있습니다. JDK7에 있어야합니다.


좀 더 구체적이거나 문서 링크를 게시 할 수 있습니까? 이 아무것도 찾을 수가 없습니다 ...
루치아노

패키지 인 것 같습니다 java.nio.file. 튜토리얼을 참조하십시오 .
David L.

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

Apache Commons JCI (Java Compiler Interface)를 고려할 수도 있습니다. 이 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

다른 답변과 마찬가지로 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);
    }

  }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.