如何获得 WatchService 中的真实路径
How can I get the real path in WatchService
在java中,当我添加或更改或删除任何文件时,我希望程序在另一个directory.It中执行相同的操作意味着,如果我在"test.txt"中添加一个文件E://aaa,程序应该从E://aaa复制"test.txt"到D://bbb。
我使用java.nio.file.WatchService
来实现它,但是我无法在程序中获取文件的真实路径,这是我的代码:
public void watchPath(Path watchPath, Path targetPath) throws IOException, InterruptedException {
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
watchPath.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY,
StandardWatchEventKinds.ENTRY_DELETE);
while (true) {
final WatchKey key = watchService.take();
for (WatchEvent<?> watchEvent : key.pollEvents()) {
final Kind<?> kind = watchEvent.kind();
if (kind == StandardWatchEventKinds.OVERFLOW) {
continue;
}
final WatchEvent<Path> watchEventPath = (WatchEvent<Path>) watchEvent;
Path systemFileDir = (Path) key.watchable(); // TODO Here can not get the real path
//System.out.println(systemFileDir.toString()); // E:/aaa
//System.out.println(systemFileDir.toAbsolutePath()); // E:/aaa
//System.out.println(systemFileDir.toRealPath()); // E:/aaa
final Path path = watchEventPath.context();
String fileAbsPath = systemFileDir + File.separator + path;
Path original = Paths.get(fileAbsPath);
String targetAbsPath = fileAbsPath.replace(watchPath.toString(), targetPath.toString());
Path target = Paths.get(targetAbsPath);
File file = new File(targetAbsPath);
if (kind == StandardWatchEventKinds.ENTRY_CREATE || kind == StandardWatchEventKinds.ENTRY_MODIFY) {
if (file.isDirectory() && !file.exists()) { // 如果是目录
file.mkdirs();
} else {
Files.copy(original, target, StandardCopyOption.REPLACE_EXISTING);
}
}
if (kind == StandardWatchEventKinds.ENTRY_DELETE) {
Files.delete(target);
}
}
boolean valid = key.reset();
if (!valid) {
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
现在的问题是,当我在E://aaa/x中添加文件或目录时,程序无法获取真实路径。比如我添加了文件E://aaa/x/test.txt,我希望能得到这个绝对路径然后复制到destination,但是我得到的只是RootPath E://aaa。
我该如何解决?谢谢!
根据您的评论:
您遇到问题的原因是您只注册了父文件夹。如果您想获得在子文件夹中所做编辑的确切路径,那么您还需要在这些子文件夹中注册您的观察者。一种方法是 walk through the entire file tree 一开始就注册所有内容。
这是一个完美的例子:
现在您只需修改该代码片段以满足您的需要,方法是调整 processEvents()
方法来检查事件类型,然后使用 child
变量在您的其他文件夹中执行相同的操作.
这是您可以对 processEvents 进行编辑以在镜像目录中添加文件夹的粗略示例:
Path child = dir.resolve(name);
if (kind == StandardWatchEventKinds.ENTRY_CREATE && (check if directory here))
{
String destinationToMirror = "D" + child.toString().substring(1);
File file = new File(destinationToMirror);
file.mkdir();
}
否则请继续阅读遍历文件树,这样您就可以将必要的位添加到您自己的代码中:
http://docs.oracle.com/javase/tutorial/essential/io/walk.html
原答案:
试试这样:
Path original = systemFileDir.resolve(watchEventPath.context());
而不是:
final Path path = watchEventPath.context();
String fileAbsPath = systemFileDir + File.separator + path;
Path original = Paths.get(fileAbsPath);
请注意主要区别在于如何使用 dir.resolve
解析路径
来源:java.nio.file.WatchEvent gives me only relative path. How can I get the absolute path of the modified file?
在java中,当我添加或更改或删除任何文件时,我希望程序在另一个directory.It中执行相同的操作意味着,如果我在"test.txt"中添加一个文件E://aaa,程序应该从E://aaa复制"test.txt"到D://bbb。
我使用java.nio.file.WatchService
来实现它,但是我无法在程序中获取文件的真实路径,这是我的代码:
public void watchPath(Path watchPath, Path targetPath) throws IOException, InterruptedException {
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
watchPath.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY,
StandardWatchEventKinds.ENTRY_DELETE);
while (true) {
final WatchKey key = watchService.take();
for (WatchEvent<?> watchEvent : key.pollEvents()) {
final Kind<?> kind = watchEvent.kind();
if (kind == StandardWatchEventKinds.OVERFLOW) {
continue;
}
final WatchEvent<Path> watchEventPath = (WatchEvent<Path>) watchEvent;
Path systemFileDir = (Path) key.watchable(); // TODO Here can not get the real path
//System.out.println(systemFileDir.toString()); // E:/aaa
//System.out.println(systemFileDir.toAbsolutePath()); // E:/aaa
//System.out.println(systemFileDir.toRealPath()); // E:/aaa
final Path path = watchEventPath.context();
String fileAbsPath = systemFileDir + File.separator + path;
Path original = Paths.get(fileAbsPath);
String targetAbsPath = fileAbsPath.replace(watchPath.toString(), targetPath.toString());
Path target = Paths.get(targetAbsPath);
File file = new File(targetAbsPath);
if (kind == StandardWatchEventKinds.ENTRY_CREATE || kind == StandardWatchEventKinds.ENTRY_MODIFY) {
if (file.isDirectory() && !file.exists()) { // 如果是目录
file.mkdirs();
} else {
Files.copy(original, target, StandardCopyOption.REPLACE_EXISTING);
}
}
if (kind == StandardWatchEventKinds.ENTRY_DELETE) {
Files.delete(target);
}
}
boolean valid = key.reset();
if (!valid) {
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
现在的问题是,当我在E://aaa/x中添加文件或目录时,程序无法获取真实路径。比如我添加了文件E://aaa/x/test.txt,我希望能得到这个绝对路径然后复制到destination,但是我得到的只是RootPath E://aaa。
我该如何解决?谢谢!
根据您的评论:
您遇到问题的原因是您只注册了父文件夹。如果您想获得在子文件夹中所做编辑的确切路径,那么您还需要在这些子文件夹中注册您的观察者。一种方法是 walk through the entire file tree 一开始就注册所有内容。
这是一个完美的例子:
现在您只需修改该代码片段以满足您的需要,方法是调整 processEvents()
方法来检查事件类型,然后使用 child
变量在您的其他文件夹中执行相同的操作.
这是您可以对 processEvents 进行编辑以在镜像目录中添加文件夹的粗略示例:
Path child = dir.resolve(name);
if (kind == StandardWatchEventKinds.ENTRY_CREATE && (check if directory here))
{
String destinationToMirror = "D" + child.toString().substring(1);
File file = new File(destinationToMirror);
file.mkdir();
}
否则请继续阅读遍历文件树,这样您就可以将必要的位添加到您自己的代码中: http://docs.oracle.com/javase/tutorial/essential/io/walk.html
原答案:
试试这样:
Path original = systemFileDir.resolve(watchEventPath.context());
而不是:
final Path path = watchEventPath.context();
String fileAbsPath = systemFileDir + File.separator + path;
Path original = Paths.get(fileAbsPath);
请注意主要区别在于如何使用 dir.resolve
来源:java.nio.file.WatchEvent gives me only relative path. How can I get the absolute path of the modified file?