我正在为任何新文件夹和文件创建的根目录和子目录开发Java Watcher服务。我的根目录是C:/REST API/source/
。这是我的文件夹结构,可能看起来像默认创建根目录,子目录由最终用户创建
C:/REST API/source/
- /source/new folder
-/source/new folder/new folder
-/source/new folder(2)
我的程序会将C:/REST API/source/
注册为根目录,如果检测到在C:/REST API/source/
中创建了新文件夹,它将注册C:/REST API/source/new folder
的路径。正在测试/source/new folder/new folder
的相同过程并且它运行良好。但是当我尝试在/source/
目录下再次创建新文件夹时,我发现路径不正确
这是我的编译器声明
1
2
3
a
b
C:\REST API\source
c
d
e
C:\REST API\source
4
5
6
7
8
9
New folder
C:\REST API\source\New folder
file:///C:/REST%20API/source/New%20folder/
10
C:\REST API\source\New folder
11
12
13
aa
bb
C:\REST API\source\New folder
cc
dd
ee
14
C:\REST API\source\New folder
The new file :C:\REST API\source\New folderEvent :ENTRY_CREATE
5
6
7
8
9
New folder
C:\REST API\source\New folder\New folder
file:///C:/REST%20API/source/New%20folder/New%20folder/
10
C:\REST API\source\New folder\New folder
11
12
13
aa
bb
C:\REST API\source\New folder\New folder
cc
dd
ee
14
C:\REST API\source\New folder\New folder
The new file :C:\REST API\source\New folder\New folderEvent :ENTRY_CREATE
5
6
7
8
9
New folder (2)
C:\REST API\source\New folder\New folder\New folder (2)
file:///C:/REST%20API/source/New%20folder/New%20folder/New%20folder%20(2)
10
C:\REST API\source\New folder\New folder\New folder (2)
11
The new file :C:\REST API\source\New folder\New folder\New folder (2)Event :ENTRY_CREATE
5
是否能够注册回根目录或检测用户已访问的目录,因此如果当前用户访问当前目录,则观察者服务将再次注册目录已由用户先前创建。因为我发现它是由path=child
造成的。如果我没有覆盖子路径变量,如果我将文件放入受监控的目录,我将无法检索文件路径
public class fileStatus {
public static void main(String [] args) throws FileNotFoundException, IOException, JSONException, InterruptedException
{
try(WatchService svc = FileSystems.getDefault().newWatchService())
{
System.out.println("1");
Map<WatchKey, Path> keyMap = new HashMap<>();
System.out.println("2");
Path path = Paths.get("C:/REST API/source/");
System.out.println("3");
fileStatus.registerAll(path,keyMap,svc);
System.out.println(path);
System.out.println("4");
WatchKey wk ;
do
{
System.out.println("5");
wk = svc.take();
System.out.println("6");
for(WatchEvent<?> event : wk.pollEvents())
{
System.out.println("7");
WatchEvent.Kind<?> type = event.kind();
System.out.println("8");
Path fileName = (Path)event.context();
System.out.println("9");
System.out.println(fileName);
Path child = path.resolve(fileName);
URI uri = child.toUri();
System.out.println(child);
System.out.println(uri);
System.out.println("10");
Path newPath = Paths.get(uri);
System.out.println(newPath);
System.out.println("11");
if (Files.isDirectory(newPath, LinkOption.NOFOLLOW_LINKS))
{
System.out.println("12");
if(type == StandardWatchEventKinds.ENTRY_CREATE)
{
System.out.println("13");
register(newPath,keyMap,svc);
System.out.println("14");
System.out.println(newPath);
child=newPath;
}
}
System.out.println("\nThe new file :"+child+ "Event :" +type);
path = child ;
}
}while(wk.reset());
}
catch(IOException e)
{
e.printStackTrace();
}
}
private static Path register(Path newPath, Map<WatchKey, Path> keyMap, WatchService svc) throws IOException
{
System.out.println("aa");
Files.walkFileTree(newPath,new SimpleFileVisitor<Path>()
{
public FileVisitResult preVisitDirectory(Path newPath, BasicFileAttributes attrs) throws IOException
{
System.out.println("bb");
System.out.println(newPath);
if(attrs.isDirectory())
{
System.out.println("cc");
keyMap.put(newPath.register(svc, StandardWatchEventKinds.ENTRY_CREATE),newPath);
}
System.out.println("dd");
return FileVisitResult.CONTINUE;
}
});
System.out.println("ee");
return newPath;
}
private static Path registerAll(Path path, Map<WatchKey, Path> keyMap, WatchService svc) throws IOException
{
System.out.println("a");
Files.walkFileTree(path,new SimpleFileVisitor<Path>()
{
public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes attrs) throws IOException
{
System.out.println("b");
System.out.println(path);
if(attrs.isDirectory())
{
System.out.println("c");
keyMap.put(path.register(svc, StandardWatchEventKinds.ENTRY_CREATE),path);
}
System.out.println("d");
return FileVisitResult.CONTINUE;
}
});
System.out.println("e");
return path;
}
}
答案 0 :(得分:1)
代码的问题是path
在child
循环结束时设置为while
。这意味着如果
a/
,路径设置为a
a/b/
,并将路径设置为a/b/
a/c/
。它从c
返回(Path) event.context()
。但它会在下一个代码a/b/
与路径path.resolve(fileName)
匹配。它会为您a/b/c/
而不是a/c
不幸的是WatchService
不允许获取填充该事件的directory
。您可以为每个现有/新目录创建单独的WatchService
,但这可能过度。
我建议使用特殊的Sun类ExtendedWatchEventModifier.FILE_TREE
来跟踪目录及其所有子目录。在这种情况下,如果跟踪a
并创建了a/b/c
,则Path
获得的WatchEvent
将为b/c
,您将能够解析它使用根路径。请看下面的粗略代码:
import com.sun.nio.file.ExtendedWatchEventModifier;
import org.json.JSONException;
import java.io.IOException;
import java.net.URI;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
public class fileStatus {
public static void main(String[] args) throws IOException, JSONException, InterruptedException {
try (WatchService svc = FileSystems.getDefault().newWatchService()) {
final Path path = Paths.get("C:/ADovzhenko/watch_dir");
registerAll(path, svc);
WatchKey wk;
do {
wk = svc.take();
for (WatchEvent<?> event : wk.pollEvents()) {
WatchEvent.Kind<?> type = event.kind();
Path child = path.resolve((Path) event.context());
URI uri = child.toUri();
System.out.println("Created: " + child);
}
} while (wk.reset());
}
}
private static Path registerAll(Path path, final WatchService svc) throws IOException {
//Register folder and its sub-folders
path.register(svc, new WatchEvent.Kind<?>[]{StandardWatchEventKinds.ENTRY_CREATE}, ExtendedWatchEventModifier.FILE_TREE);
//Print all existing directories
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
public FileVisitResult preVisitDirectory(final Path dir, BasicFileAttributes attrs) throws IOException {
if (attrs.isDirectory()) {
System.out.println("Existing: " + dir);
return FileVisitResult.CONTINUE;
}
//In case if print of non-directory is required
//System.out.println("Existing: " + dir);
return FileVisitResult.SKIP_SIBLINGS;
}
});
return path;
}
}