Java NIO.2 使用Path接口來監聽文件、文件夾變化

 

Java7對NIO進行了大的改進,新增了許多功能:java

  • 對文件系統的訪問提供了全面的支持
  • 提供了基於異步Channel的IO

這些新增的IO功能簡稱爲 NIO.2,依然在java.nio包下。安全

 

 

 

早期的Java只提供了File類來操做文件、文件夾自己,功能有限,性能也不高。異步

NIO.2爲解決這種缺陷,提供了Path接口,並提供了Paths、Files2個工具類,這2個工具類包含的方法都是靜態方法,Files類提供了大量的靜態方法來操做文件、文件夾。工具

 

Path接口、Paths工具類使用示例:性能

 1  //獲取指定路徑的Path對象
 2         Path path=Paths.get("D:/untitled/test/");   
 3         //也能夠這樣寫:   Path path=Paths.get("D","untitled","test");    參數個數可變
 4 
 5         //返回文件/文件夾名,test
 6         System.out.println(path.getFileName());
 7         //返回父目錄的路徑,D:\untitled
 8         System.out.println(path.getParent());
 9         //判斷該路徑的最後一級是不是指定的文件/文件夾,true。和String的endsWith有點不一樣。當參數是最後一級的文件/文件夾名時,才返回true。
10         System.out.println(path.endsWith("test"));    
11         //以上方法的操做對象是Path對象中的路徑,就是說路徑沒必要是真實存在的
12 
13         //返回根路徑(盤符),D:\
14         System.out.println(path.getRoot());
15         //返會絕對路徑
16         System.out.println(path.toAbsolutePath());   
17         //以上獲取的路徑要是真實存在的

 

 

 

 

 

之前,若是要監控文件、目錄的變化(新建、修改、刪除),通常是啓動一條後臺線程,這條線程每隔一段時間去遍歷指定目錄的文件,若是這次遍歷的結果與上次遍歷的結果不一樣,就認爲文件發生了變化。這種方式很繁瑣,性能也低。測試

 

NIO.2的Path接口提供了一個方法來監聽文件變化:spa

register(WatchService watcher, 要監聽的事件類型1,要監聽的事件類型2,.......)       //註冊一個監聽服務線程

 

好比「xx安全衛士提醒您:xx程序將建立xx文件,是否容許?」、「xx程序試圖修改xx文件,是否容許?」,就可以使用此方法實現。code

 

使用示例:對象

 1 public class Test {
 2     public static void main(String[] args) throws IOException, InterruptedException {
 3 
 4         //建立一個文件系統的監聽服務
 5         WatchService watchService= FileSystems.getDefault().newWatchService();
 6 
 7         Path path=Paths.get("D:/untitled/test");
 8         
 9         //爲該文件夾註冊監聽,監聽新建、修改、刪除事件。只能爲文件夾(目錄)註冊監聽,不能爲單個文件註冊監聽
10         path.register(watchService,StandardWatchEventKinds.ENTRY_CREATE,StandardWatchEventKinds.ENTRY_MODIFY,StandardWatchEventKinds.ENTRY_DELETE);
11 
12         //編寫事件處理
13         while (true){  //一直監聽
14             //拉取一個WatchKey。當觸發監聽的事件時,就會產生一個WatchKey,此WatchKey封裝了事件信息。
15             WatchKey watchKey=watchService.take();
16 
17             //使用循環是由於這一個WatchKey中可能有多個文件變化了,好比Ctrl+A全選,而後刪除,只觸發了一個WatchKey,但有多個文件變化了
18             for (WatchEvent event:watchKey.pollEvents()){   
19                 System.out.println(event.context()+"發生了"+event.kind()+"事件!");
20                 /*
21                 watchKey.pollEvents()  獲取這次WatchKey中全部變化了的文件的信息,以List(列表)形式返回,一個WatchEvent就是一個元素,封裝了一個變化了的文件的信息
22                 event.context()  獲取文件名
23                 event.kind()  獲取發生的事件類型
24 
25                 由於只能爲文件夾註冊監聽,若是要監聽某些指定的文件,能夠在加強的for循環中,先根據event.context()判斷是不是指定的文件,是才處理。
26                  */
27             }
28 
29             //雖然是while()循環,但WatchKey和ByteBuffer同樣,使用完要重置狀態,才能繼續用。
30             watchKey.reset();    //若是不重置,WatchKey使用一次事後就不能再使用,即只能監聽到一次文件變化。
31         }
32 
33 
34         /*
35         測試:在D:/untitled/test目錄下
36         一、新建1.txt文件      1.txt.txt發生了ENTRY_CREATE事件!
37         二、打開1.txt,輸入"hello world!",並保存      1.txt.txt發生了ENTRY_MODIFY事件!
38         三、刪除「hello world!",並保存      1.txt.txt發生了ENTRY_MODIFY事件!
39         四、新建2.txt文件    2.txt發生了ENTRY_CREATE事件!
40 
41         說明:編輯文件內容時,不算修改,保存時纔算修改。
42 
43         五、新建文件夾「圖片」
44             新建文件夾發生了ENTRY_CREATE事件!
45             新建文件夾發生了ENTRY_DELETE事件!
46             圖片發生了ENTRY_CREATE事件!
47         OS執行過程:新建了一個名爲「新建文件夾」的文件夾,再把此文件夾重命名爲指定的名稱。
48         重命名時,」新建文件夾「消失了,算做刪除,」圖片「出現了,算做新建。
49 
50         六、在圖片目錄下,隨便新建一個文件或者文件夾
51             圖片發生了ENTRY_MODIFY事件!
52          說明監控的只是子文件、子文件夾,不會遞歸監控。
53 
54         七、全選,刪除test下全部文件、子文件夾
55             圖片發生了ENTRY_DELETE事件!
56             1.txt.txt發生了ENTRY_DELETE事件!
57             2.txt發生了ENTRY_DELETE事件!
58          */
59 
60 
61     }
62 }

 

 

拉取一個WatchKey有3種方法:

  • WatchKey  take()   //阻塞式拉取,若是未拉取到,會一直等待,直到拉取到一個WatchKey。通常咱們用這個。
  • WatchKey   poll()   //非阻塞式拉取,試圖拉取一個WatchKey,拉取到了就返回拉取的WatchKey對象,沒有WatchKey發生就當即返回null。
  • WatchKey   poll(long  timeout, TimeUnit  unit)    //非阻塞式拉取,若是沒拉取到,會再等待timeout毫秒,還沒拉取到才返回null。
相關文章
相關標籤/搜索