파일 시스템에서 파일이 변경되었을 때 알림을 받고 싶습니다. lastModified File 속성을 폴링하는 스레드 만 발견했으며이 솔루션은 최적이 아닙니다.
파일 시스템에서 파일이 변경되었을 때 알림을 받고 싶습니다. lastModified File 속성을 폴링하는 스레드 만 발견했으며이 솔루션은 최적이 아닙니다.
답변:
낮은 수준에서이 유틸리티를 모델링하는 유일한 방법은 디렉터리에서 스레드를 폴링하고 파일의 속성을 감시하는 것입니다. 그러나 패턴을 사용하여 이러한 유틸리티 용 어댑터를 개발할 수 있습니다.
예를 들어 Tomcat 등의 j2ee 애플리케이션 서버에는 배포 설명자가 변경되거나 서블릿 클래스가 변경되는 즉시 애플리케이션이 다시 시작되는 자동로드 기능이 있습니다.
대부분의 tomcat 코드는 재사용 가능하고 오픈 소스이므로 이러한 서버의 라이브러리를 사용할 수 있습니다.
이전에 로그 파일 모니터를 작성했는데, 1 초에 몇 번씩 단일 파일의 속성을 폴링 할 때 시스템 성능에 미치는 영향이 실제로 매우 작다는 것을 발견했습니다.
Java 7, NIO.2의 일부로 WatchService API 가 추가되었습니다.
WatchService API는 파일 변경 이벤트에 대한 알림을 받아야하는 애플리케이션을 위해 설계되었습니다.
Apache Commons의 VFS API를 사용합니다. 다음은 성능에 큰 영향을주지 않고 파일을 모니터링하는 방법의 예입니다.
Java commons-io에는 FileAlterationObserver가 있습니다. FileAlterationMonitor와 결합하여 폴링을 수행합니다. Commons VFS와 유사합니다. 장점은 종속성이 훨씬 적다는 것입니다.
편집 : 더 적은 종속성은 사실이 아니며 VFS의 경우 선택 사항입니다. 그러나 VFS 추상화 계층 대신 Java 파일을 사용합니다.
"더 많은 NIO 기능"에는 기본 OS에 따라 구현되는 파일 감시 기능이 있습니다. 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를 사용하여 파일 변경 사항을 수신 할 수 있습니다. 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();
}
}
약간의 돈을 벌고 싶다면 JNIWrapper는 Winpack이있는 유용한 라이브러리이며 특정 파일에 대한 파일 시스템 이벤트를 얻을 수 있습니다. 불행히도 창문 만.
https://www.teamdev.com/jniwrapper를 참조 하십시오 .
그렇지 않으면 네이티브 코드에 의존하는 것이 항상 나쁜 것은 아닙니다. 특히 최상의 제안이 네이티브 이벤트에 대한 폴링 메커니즘 인 경우에는 더욱 그렇습니다.
일부 컴퓨터에서는 Java 파일 시스템 작업이 느려질 수 있으며 제대로 처리되지 않으면 응용 프로그램의 성능에 쉽게 영향을 미칠 수 있습니다.
Apache Commons JCI (Java Compiler Interface)를 고려할 수도 있습니다. 이 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);
}
}
}