2017-01-03 50 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