2013-04-21 14 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(); 
     }  
    } 
} 

私はこれを実行し、その後、私は出力を得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で見られる動作は、Notepad ++と、IO操作を実行する際にWindowsオペレーティングシステムが動作する方法を拡張しているためです。私は、 "標準の" Windowsのメモ帳のようなものが、通常、最も期待される動作を生成することを発見しました。私はProcess Explorer(http://technet.microsoft.com/en-gb/sysinternals/bb896653)を使用すると思われます。aspx)を使用してOSレベルでIOアクティビティを監視すると、同じ結果が表示されます。 –

+2

これは、コンテンツとメタデータの書き込みが別々に実行されるためです。 – afk5min

答えて

0

私のシステム(Windows 7 + 1.7.0_21)でファイルの作成と削除のイベントが正しく機能しています。

変更イベントメッセージは、そのファイルの各Ctrlキー + S動作の時間の(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

ウォッチサービスの変更イベントが2つのイベントを生成するために、これは動作します。すでに存在するファイルを変更すると、ファイルシステムは最初に0バイトでそれを作成し、変更イベントを発生させてデータを書き込みます。次に、変更イベントを再度発生させます。そのため、2つの変更イベントが表示されていました。だから、私はこの問題を解決するために行っている、私はちょうど私の仕事をチェックするためにカウンタを使用していても、私は小さなFileWatcherユーティリティライブラリを作成し

 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

を数えるだけ一度にトリガする必要があります。 https://github.com/finsterwalder/fileutils

それはすることができます猶予期間を設定します。猶予期間内の複数のイベントは蓄積され、1回だけトリガーされます。

Notepad ++が何をしているのかわからないので、実験にNotepad ++を使用しないでください。メモ帳++が実際にファイルに何度も書き込んでいる可能性があります。あるいは、別の名前のファイルを書き込んで、名前を変更したときなどに名前を変更することもできます。 ファイルを操作してそれを監視する独自のコードを記述します。

関連する問題