根据用户操作更改观察者服务

时间:2017-01-03 08:09:10

标签: java nio

我正在为任何新文件夹和文件创建的根目录和子目录开发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;
    }

}

1 个答案:

答案 0 :(得分:1)

代码的问题是pathchild循环结束时设置为while。这意味着如果

  1. 默认情况下会跟踪目录a/,路径设置为a
  2. 然后创建目录a/b/,并将路径设置为a/b/
  3. 然后创建目录a/c/。它从c返回(Path) event.context()。但它会在下一个代码a/b/与路径path.resolve(fileName)匹配。它会为您a/b/c/而不是a/c
  4. 不幸的是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;
        }
    
    }