[英]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.