2017-01-03 30 views
0

我正在为任何新建文件夹和文件创建的根目录和子目录开发Java观察器服务。我的根目录是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

与代码的问题是,path是在while循环结束时设置为child。这意味着,如果

  1. 目录a/默认情况下,跟踪,路径设置为a
  2. 然后创建目录a/b/和路径设置为a/b/
  3. 然后目录a/c/被创建。它从(Path) event.context()返回c。但是通过下一个代码path.resolve(fileName)与路径a/b/相匹配。它给你a/b/c/代替a/c

不幸的是WatchService不允许得到directory其填充事件。您可以为每个现有的/新目录创建单独的WatchService,但这可能是矫枉过正。

我会建议使用特殊的Sun的课ExtendedWatchEventModifier.FILE_TREE跟踪目录及其所有子目录。在这种情况下,如果跟踪a并且创建了a/b/c,那么从WatchEvent得到的Path将为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; 
    } 

} 
+0

将寄存器方法采取ExtendedWatchEventModifier.FILE_TREE作为参数?我发现它可能不支持 – yumi

+0

它仅在Windows平台上受支持,但由于'C:/'文件路径的原因,我认为您使用的是Windows。 –

+0

是否为register()的ExtendedWatchEventModifier.FILE_TREE有效参数?因为当我尝试使用path.register(svc,new WatchEvent.Kind [] {StandardWatchEventKinds.ENTRY_CREATE},ExtendedWatchEventModifier.FILE_TREE)时,我的编译器返回了错误; ,看起来像ExtendedWatchEventModifier.FILE_TREE不能分配给register()方法 – yumi