2013-04-21 2 views
23
import java.io.*; 
import java.nio.file.*; 

public class Tmp { 

    public static void main(String [] args) throws IOException { 
     int count = 0; 
     Path path = Paths.get("C:\\tmp\\"); 
     WatchService ws = null; 
     try { 
      ws = FileSystems.getDefault().newWatchService(); 
      path.register(ws, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, 
        StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.OVERFLOW); 
     } catch (IOException ioe) { 
      ioe.printStackTrace(); 
     } 

     while(true) { 
      WatchKey key = null; 
      try { 
       key = ws.take(); 
      } catch(InterruptedException ie) { 
       ie.printStackTrace(); 
      } 

      for(WatchEvent<?> event: key.pollEvents()) { 
       switch(event.kind().name()) { 
        case "OVERFLOW": 
         System.out.println(++count + ": OVERFLOW"); 
         break; 
        case "ENTRY_MODIFY": 
         System.out.println(++count + ": File " + event.context() + " is changed!"); 
         break; 
        case "ENTRY_CREATE": 
         System.out.println(++count + ": File " + event.context() + " is created!"); 
         break; 
        case "ENTRY_DELETE": 
         System.out.println(++count + ": File " + event.context() + " is deleted!"); 
         break; 
        default: 
         System.out.println(++count + ": UNKNOWN EVENT!"); 
       } 
      } 

      key.reset(); 
     }  
    } 
} 

내가 이것을 실행 한 다음 메모장을 열어 ++ 다음 새 빈 파일을 생성 I 출력 얻은 C:\tmp\ 디렉토리에 a.txt로 저장 :왜 WatchService가 많은 연산을 생성합니까?

1: File a.txt is created! 
2: File a.txt is deleted! 
3: File a.txt is created! 

그 이유는 무엇입니까? 파일이 생성 된 다음 삭제 된 다음 다시 생성 된 것 같습니다. 왜? 내가 파일에 텍스트를 넣어 저장하면이 출력은

을했다 :

4: File a.txt is changed! 
5: File a.txt is changed! 

왜 두 번 변경 했습니까?

+5

WatchService에서 볼 수있는 동작은 메모장 + + 및 IO 작업 수행시 Windows 운영 체제의 작동 방식에 따라 다릅니다. "표준"Windows 메모장과 같은 것이 일반적으로 가장 기대되는 동작을 생성한다는 것을 발견했습니다. 프로세스 탐색기 (http://technet.microsoft.com/en-gb/sysinternals/bb896653)를 사용하면 의심 스럽습니다.aspx) OS 수준에서 IO 작업을 모니터링하려면 동일한 결과가 나타납니다. –

+2

이것은 컨텐츠와 메타 데이터 쓰기가 개별적으로 수행되기 때문일 수 있습니다. – afk5min

답변

0

내 시스템 (Window 7 + 1.7.0_21)에서 파일 생성 및 삭제 이벤트가 올바르게 작동하고 있습니다.

변경 이벤트 메시지

해당 파일의 각 Ctrl 키 + 작업에 시간의 (N)의 수를 표시합니다.

 // Removed the "//" after director name as D://tmp" 
     //Added just to see the message with a 1 ms gap. 
     Thread.sleep(1000); // after key.reset(); 

예 : 우리가 파일을 열고 CRTL + S를 누르면 계속 경우 가 (변화/변경에서 함께 저장). 각 메시지 저장 조작에 대해 다음 메시지가 (반복적으로) 표시됩니다.

 File YourFileName.txt is changed! 

이유는 WatchService가 파일 변경 사항을 체크섬 대신 타임 스탬프와 비교하는 이유입니다.

자세한 설명은 여기 Platform dependencies

+0

1ms 간격이 아니라 1 초 간격입니다. 물론 다시 확인하기 전에 컴퓨터 용어로 매우 오랜 시간 기다리는 경우에는 효과를 볼 수 없습니다. 이것에 관해서는 : "이유는 WatchService가 체크섬 대신 파일 변경을 타임 스탬프와 비교하는 이유입니다." 어 ... 뭐라구? –

+0

@RobinGreen, 귀하의 예외와 귀하의 대답은 무엇인지 말해주십시오. – VKPRO

0

주어진 날

// get the first event before looping 
    WatchKey key = this.watcher.take(); 

    // reset key (executed twice but not invoke the polled events) 
    while (key != null && key.reset()) { 
     // polled events 
     for (final WatchEvent<?> event : key.pollEvents()) { 
     System.out.printf("\nGlobal received: %s, event for file: %s\n", event.kind(), 
      event.context()); 

     switch (event.kind().name()) { 
     case "ENTRY_CREATE": 
      LOGGER.debug("event ENTRY_CREATE"); 
      break; 
     case "ENTRY_DELETE": 
      LOGGER.debug("event ENTRY_DELETE"); 
      break; 
     case "ENTRY_MODIFY": 
      LOGGER.debug("event ENTRY_MODIFY"); 
      break; 
     default: 
      LOGGER.debug("event other [OVERFLOW]"); 
      break; 
     } 
     } 

     key = this.watcher.take(); 
    } 
1

시계 서비스의 수정 이벤트가이 이벤트를 생성이 작동합니다. 이미 존재하는 파일을 수정할 때 파일 시스템은 먼저 0 바이트로 파일 시스템을 생성하고 수정 이벤트를 발생시킨 다음 데이터를 기록합니다. 그런 다음 modify 이벤트를 다시 발생시킵니다. 그것이 두 가지 수정 이벤트를 보여주는 이유입니다. 그래서이 문제를 해결하기 위해 무슨 짓, 난 그냥도

 Path path = null; 
     int count = 0; 

     try { 
      path = Paths.get(new Utility().getConfDirPath()); 
      System.out.println("Path: " + path); 
     } catch (UnsupportedEncodingException e1) { 
      e1.printStackTrace(); 
     } 

     WatchService watchService = null; 
     try { 
      watchService = FileSystems.getDefault().newWatchService(); 
      path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY,StandardWatchEventKinds.ENTRY_DELETE); 
     } catch (IOException ioe) { 
      ioe.printStackTrace(); 
     } 


     while(true) { 
      WatchKey key = null; 
      try { 
       key = watchService.take(); 
      } catch(InterruptedException ie) { 
       ie.printStackTrace(); 
      } 

      for(WatchEvent<?> event: key.pollEvents()) { 
       switch(event.kind().name()) { 
        case "ENTRY_MODIFY": 
         System.out.println(++count + ": File " + event.context() + " is changed!"); 

         if (count%2==0) { 
          doOnChange(); // do whatever you want 
         } 
         break; 
        case "ENTRY_DELETE": 
         System.out.println(++count + ": File " + event.context() + " is deleted!"); 
         break; 
        default: 
         System.out.println(++count + ": UNKNOWN EVENT!"); 
       } 
      } 

      // reset the key 
      boolean valid = key.reset(); 
      if (!valid) { 
       System.out.println("Key has been unregistered"); 
      } 

     }  
0

내가 작은 FileWatcher 유틸리티 라이브러리 생성 계산 한 번만에 트리거해야 내 작업을 확인하기 위해 카운터를 사용 그것은 할 수 있습니다 https://github.com/finsterwalder/fileutils

유예 기간을 설정하십시오. 유예 기간 내에 여러 이벤트가 누적되고 한 번만 트리거됩니다.

Notepad ++가 어떤 작업을하는지 모르기 때문에 실험에 Notepad ++를 사용하면 안됩니다. Notepad ++가 실제로 파일에 여러 번 쓰고있는 것일 수도 있습니다. 또는 다른 이름의 파일을 작성하고 이름을 바꿀 수 있습니다. 파일을 조작하고 보려는 코드를 직접 작성하십시오.

관련 문제