简体   繁体   English

重命名目录后 WatchService 目录路径不正确

[英]WatchService Directory path incorrect after renaming Directory

The code registers any new directory created with the watch service to listen for all the events and runs for a duration of 60 seconds[which can be changed with running time]该代码注册使用监视服务创建的任何新目录以侦听所有事件并运行 60 秒[可以随运行时间更改]

final class Test 
{
 public static void main(String[] args)throws Exception
 {
  //Run the program for 60 seconds i.e * 1000
  long RUNNING_TIME=60*1000;
  
  try(WatchService service=FileSystems.getDefault().newWatchService())
  {
   //Register test directory for observation
   Path.of("E:","Folder A").register(service,StandardWatchEventKinds.ENTRY_CREATE,StandardWatchEventKinds.ENTRY_MODIFY,StandardWatchEventKinds.ENTRY_DELETE);
   
   long start=System.currentTimeMillis();
   while(System.currentTimeMillis()-start<RUNNING_TIME)
   {
    //Use poll not take else while loop will be blocked
    WatchKey key=service.poll();
    
    if(key==null){continue;}
    for(WatchEvent event:key.pollEvents())
    {
    //Get the absolute path from the event context by resolving it against it's parent directory
     Path
     eventPath=(Path)event.context(),
     absolutePath=((Path)key.watchable()).resolve(eventPath); //Wrong path after resolving against watchable after renaming directory
     Kind kind=event.kind();
     
     //If the event kind is CREATE and an new directory is created then register that directory with the service
     if(kind==StandardWatchEventKinds.ENTRY_CREATE && Files.isDirectory(absolutePath))
     {
      absolutePath.register
      (
       service,
       StandardWatchEventKinds.ENTRY_CREATE,
       StandardWatchEventKinds.ENTRY_MODIFY,
       StandardWatchEventKinds.ENTRY_DELETE
      );
     }
     
     //Debugging
     System.out.println("Event Path="+eventPath);
     System.out.println("Absolute Path="+absolutePath);
     System.out.println("Kind="+kind);
     System.out.println("==========================");
    }
   
    key.reset();
   }  
  }
 }
}

Here are the observed results以下是观察到的结果

Sno                            Test                                  Output

1       Create Directory=>E:/Folder A/New Folder               Event Path=New folder
                                                          Absolute Path=E:\Folder A\New folder
                                                                 Kind=ENTRY_CREATE
                                                             ==========================



2        Rename E:/Folder A/New Folder                         Event Path=New folder
                       TO                                 Absolute Path=E:\Folder A\New folder
                     E:/Folder A/Test                           Kind=ENTRY_DELETE
                                                            ==========================
                                                               Event Path=Test
                                                         Absolute Path=E:\Folder A\Test
                                                               Kind=ENTRY_CREATE



3        Create Text File Under Test Folder i.e            Event Path=New Text Document.txt
     Create => E:/Folder A/Test/New Text Document.txt     Absolute Path=E:\Folder A\New folder\New Text Document.txt
                                                             Kind=ENTRY_CREATE
                                                            ==========================
                                                             Event Path=Test
                                                          Absolute Path=E:\Folder A\Test
                                                             Kind=ENTRY_MODIFY




4    Rename  E:/Folder A/Test/New Text Document.txt        Event Path=New Text Document.txt
                   To                                 Absolute Path=E:\Folder A\New folder\New Text Document.txt
            E:/Folder A/Test/Test.txt                      Kind=ENTRY_DELETE
                                                        ==========================
                                                          Event Path=Test.txt
                                                      Absolute Path=E:\Folder A\New folder\Test.txt
                                                           Kind=ENTRY_CREATE                                                          
                                                        ==========================
                                                            Event Path=Test
                                                      Absolute Path=E:\Folder A\Test
                                                          Kind=ENTRY_MODIFY
                                                        

Incorrect results appear from Test case 3 in the Absolute path Here are the incorrect absolute path values from test case 3 onwards绝对路径中的测试用例 3 出现不正确的结果这是从测试用例 3 开始的不正确的绝对路径值

Absolute Path=E:\Folder A\New folder\New Text Document.txt
Absolute Path=E:\Folder A\New folder\Test.txt

As you can see In test case 2 i have renamed my Folder from New Folder To Test so why is it still appearing while resolving against the watchable directory.如您所见,在测试用例 2 中,我已将我的文件夹从要测试的新文件夹重命名,那么为什么在解析可观察目录时它仍然出现。

Clearly the error lies in the Path returned from watchable() or maybe i should cancel this key during renaming or some other situation to get correct results.显然错误在于从 watchable() 返回的路径,或者我应该在重命名或其他情况下取消此键以获得正确的结果。

Why is watchable() method not returning the correct path after renaming the directory?为什么重命名目录后 watchable() 方法没有返回正确的路径?

You can avoid this problem if you unregister the previous watch setup for the renamed directory.如果您为重命名的目录取消注册以前的监视设置,则可以避免此问题。 When renaming, you get a DELETE then CREATE for the parent's folder watch, so you can amend the watched directories to cancel the old key, and register a new key.重命名时,您会得到一个 DELETE 然后 CREATE 用于父文件夹监视,因此您可以修改监视目录以取消旧密钥,并注册一个新密钥。

Here is your main with small adjustments for logging the keys in use and handling the delete + create using a HashMap to keep track of directories added to the watch service:这是您的主要调整,用于记录正在使用的密钥并使用HashMap处理删除 + 创建以跟踪添加到监视服务的目录:

var keys = new HashMap<Path,WatchKey>();

try (WatchService service = FileSystems.getDefault().newWatchService()) {
    // Register test directory for observation
    Path root = Path.of("C:/Temp/Folder A");

    WatchKey wk = root.register(service, StandardWatchEventKinds.ENTRY_CREATE,
            StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE);
    System.out.println("ROOT register=" + root +" wk="+wk);

    long start = System.currentTimeMillis();
    while (System.currentTimeMillis() - start < RUNNING_TIME) {
        // Use poll not take else while loop will be blocked
        WatchKey key = service.poll();

        if (key == null) {
            continue;
        }
        for (var event : key.pollEvents())  {
            // Get the absolute path from the event context by resolving it against it's
            // parent directory
            Path eventPath = (Path) event.context(), absolutePath = ((Path) key.watchable()).resolve(eventPath);

            var kind = event.kind();

            // Debugging
            System.out.println("==========================");
            System.out.println("Watch Key=" + key);
            System.out.println("Event Path=" + eventPath);
            System.out.println("Absolute Path=" + absolutePath);
            System.out.println("Kind=" + kind);

            // If the event kind is CREATE and an new directory is created then register
            // that directory with the service
            if (kind == StandardWatchEventKinds.ENTRY_CREATE && Files.isDirectory(absolutePath)) {
                var subkey = absolutePath.register(service, StandardWatchEventKinds.ENTRY_CREATE,
                        StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE);
                keys.put(absolutePath, subkey);
                System.out.println("register=" + absolutePath +" wk="+subkey);
            }
            // Deletes: wipe previously registered watch
            else if (kind == StandardWatchEventKinds.ENTRY_DELETE) {
                var prev = keys.remove(absolutePath);
                if (prev != null) {
                    System.out.println("unregister=" + absolutePath + " key="+prev);
                    prev.cancel();
                }
            }
        }

        key.reset();
    }
}

With above, starting then creating "subfolder" will report three different watch keys:如上所述,开始然后创建“子文件夹”将报告三个不同的监视键:

ROOT register=C:\Temp\Folder A wk=... $WindowsWatchKey@aaaaaaaaa

Watch Key=... $WindowsWatchKey@aaaaaaaaa
Kind=ENTRY_CREATE
register=C:\Temp\Folder A\subfolder wk=... $WindowsWatchKey@xxxxxxxx

Renaming "subfolder" to "LATEST" says:将“子文件夹”重命名为“最新”说:

Watch Key=... $WindowsWatchKey@aaaaaaaaa
Kind=ENTRY_DELETE
unregister=C:\Temp\Folder A\subfolder key=... $WindowsWatchKey@xxxxxxxx

Watch Key=... $WindowsWatchKey@aaaaaaaaa
Kind=ENTRY_CREATE
register=C:\Temp\Folder A\LATEST wk=... $WindowsWatchKey@yyyyyyyyy

Then editing a file under the new directory name will report with the current folder name, and most importantly, with the new watch key after rename not the @xxxxxxxx value it was printing before:然后在新目录名称下编辑文件将报告当前文件夹名称,最重要的是,重命名后的新监视键不是它之前打印的@xxxxxxxx值:

Watch Key=sun.nio.fs.WindowsWatchService$WindowsWatchKey@yyyyyyyyy
Event Path=file.txt
Absolute Path=C:\Temp\Folder A\LATEST\file.txt
Kind=ENTRY_MODIFY

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM