为什么 WatchService 会生成如此多的操作?

2022-09-01 21:27:24
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();
        }    
    }
}

当我运行这个,然后打开Notepad ++,然后创建一个新的空文件并将其保存在目录中时,我得到了输出:a.txtC:\tmp\

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!

为什么它改变了两次?


答案 1

观看服务的修改事件生成两个事件。当我们修改一个已经存在的文件时,文件系统首先创建一个0字节的文件,并触发一个修改事件,然后在其上写入数据。然后,它再次触发修改事件。这就是为什么它显示两个修改事件的原因。所以我做了什么来解决这个问题,我只是使用计数器来检查我的任务应该只在偶数上触发一次

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

        }    

答案 2

这对我有用

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

推荐