Java NIO.2 使用Path接口來(lái)監(jiān)聽(tīng)文件、文件夾變化
Java7對(duì)NIO進(jìn)行了大的改進(jìn),新增了許多功能:
•對(duì)文件系統(tǒng)的訪問(wèn)提供了全面的支持
•提供了基于異步Channel的IO
這些新增的IO功能簡(jiǎn)稱為 NIO.2,依然在java.nio包下。
早期的Java只提供了File類來(lái)操作文件、文件夾本身,功能有限,性能也不高。
NIO.2為解決這種缺陷,提供了Path接口,并提供了Paths、Files2個(gè)工具類,這2個(gè)工具類包含的方法都是靜態(tài)方法,F(xiàn)iles類提供了大量的靜態(tài)方法來(lái)操作文件、文件夾。
Path接口、Paths工具類使用示例:
//獲取指定路徑的Path對(duì)象
Path path=Paths.get("D:/untitled/test/");
//也可以這樣寫: Path path=Paths.get("D","untitled","test"); 參數(shù)個(gè)數(shù)可變
//返回文件/文件夾名,test
System.out.println(path.getFileName());
//返回父目錄的路徑,D:\untitled
System.out.println(path.getParent());
//判斷該路徑的最后一級(jí)是否是指定的文件/文件夾,true。和String的endsWith有點(diǎn)不同。當(dāng)參數(shù)是最后一級(jí)的文件/文件夾名時(shí),才返回true。
System.out.println(path.endsWith("test"));
//以上方法的操作對(duì)象是Path對(duì)象中的路徑,就是說(shuō)路徑不必是真實(shí)存在的
//返回根路徑(盤符),D:\
System.out.println(path.getRoot());
//返會(huì)絕對(duì)路徑
System.out.println(path.toAbsolutePath());
//以上獲取的路徑要是真實(shí)存在的
以前,如果要監(jiān)控文件、目錄的變化(新建、修改、刪除),一般是啟動(dòng)一條后臺(tái)線程,這條線程每隔一段時(shí)間去遍歷指定目錄的文件,如果此次遍歷的結(jié)果與上次遍歷的結(jié)果不同,就認(rèn)為文件發(fā)生了變化。這種方式很繁瑣,性能也低。
NIO.2的Path接口提供了一個(gè)方法來(lái)監(jiān)聽(tīng)文件變化:
register(WatchService watcher, 要監(jiān)聽(tīng)的事件類型1,要監(jiān)聽(tīng)的事件類型2,.......) //注冊(cè)一個(gè)監(jiān)聽(tīng)服務(wù)
比如“xx安全衛(wèi)士提醒您:xx程序?qū)?chuàng)建xx文件,是否允許?”、“xx程序試圖修改xx文件,是否允許?”,就可使用此方法實(shí)現(xiàn)。
使用示例:
public class Test {
public static void main(String[] args) throws IOException, InterruptedException {
//創(chuàng)建一個(gè)文件系統(tǒng)的監(jiān)聽(tīng)服務(wù)
WatchService watchService= FileSystems.getDefault().newWatchService();
Path path=Paths.get("D:/untitled/test");
//為該文件夾注冊(cè)監(jiān)聽(tīng),監(jiān)聽(tīng)新建、修改、刪除事件。只能為文件夾(目錄)注冊(cè)監(jiān)聽(tīng),不能為單個(gè)文件注冊(cè)監(jiān)聽(tīng)
path.register(watchService,StandardWatchEventKinds.ENTRY_CREATE,StandardWatchEventKinds.ENTRY_MODIFY,StandardWatchEventKinds.ENTRY_DELETE);
//編寫事件處理
while (true){ //一直監(jiān)聽(tīng)
//拉取一個(gè)WatchKey。當(dāng)觸發(fā)監(jiān)聽(tīng)的事件時(shí),就會(huì)產(chǎn)生一個(gè)WatchKey,此WatchKey封裝了事件信息。
WatchKey watchKey=watchService.take();
//使用循環(huán)是因?yàn)檫@一個(gè)WatchKey中可能有多個(gè)文件變化了,比如Ctrl+A全選,然后刪除,只觸發(fā)了一個(gè)WatchKey,但有多個(gè)文件變化了
for (WatchEvent event:watchKey.pollEvents()){
System.out.println(event.context()+"發(fā)生了"+event.kind()+"事件!");
/*
watchKey.pollEvents() 獲取此次WatchKey中所有變化了的文件的信息,以List(列表)形式返回,一個(gè)WatchEvent就是一個(gè)元素,封裝了一個(gè)變化了的文件的信息
event.context() 獲取文件名
event.kind() 獲取發(fā)生的事件類型
因?yàn)橹荒転槲募A注冊(cè)監(jiān)聽(tīng),如果要監(jiān)聽(tīng)某些指定的文件,可以在增強(qiáng)的for循環(huán)中,先根據(jù)event.context()判斷是否是指定的文件,是才處理。
*/
}
//雖然是while()循環(huán),但WatchKey和ByteBuffer一樣,使用完要重置狀態(tài),才能繼續(xù)用。
watchKey.reset(); //如果不重置,WatchKey使用一次過(guò)后就不能再使用,即只能監(jiān)聽(tīng)到一次文件變化。
}
/*
測(cè)試:在D:/untitled/test目錄下
1、新建1.txt文件 1.txt.txt發(fā)生了ENTRY_CREATE事件!
2、打開(kāi)1.txt,輸入"hello world!",并保存 1.txt.txt發(fā)生了ENTRY_MODIFY事件!
3、刪除“hello world!",并保存 1.txt.txt發(fā)生了ENTRY_MODIFY事件!
4、新建2.txt文件 2.txt發(fā)生了ENTRY_CREATE事件!
說(shuō)明:編輯文件內(nèi)容時(shí),不算修改,保存時(shí)才算修改。
5、新建文件夾“圖片”
新建文件夾發(fā)生了ENTRY_CREATE事件!
新建文件夾發(fā)生了ENTRY_DELETE事件!
圖片發(fā)生了ENTRY_CREATE事件!
OS執(zhí)行過(guò)程:新建了一個(gè)名為“新建文件夾”的文件夾,再把此文件夾重命名為指定的名稱。
重命名時(shí),”新建文件夾“消失了,算作刪除,”圖片“出現(xiàn)了,算作新建。
6、在圖片目錄下,隨便新建一個(gè)文件或者文件夾
圖片發(fā)生了ENTRY_MODIFY事件!
說(shuō)明監(jiān)控的只是子文件、子文件夾,不會(huì)遞歸監(jiān)控。
7、全選,刪除test下所有文件、子文件夾
圖片發(fā)生了ENTRY_DELETE事件!
1.txt.txt發(fā)生了ENTRY_DELETE事件!
2.txt發(fā)生了ENTRY_DELETE事件!
*/
}
}
拉取一個(gè)WatchKey有3種方法:
•WatchKey take() //阻塞式拉取,如果未拉取到,會(huì)一直等待,直到拉取到一個(gè)WatchKey。一般我們用這個(gè)。
•WatchKey poll() //非阻塞式拉取,試圖拉取一個(gè)WatchKey,拉取到了就返回拉取的WatchKey對(duì)象,沒(méi)有WatchKey發(fā)生就立即返回null。
•WatchKey poll(long timeout, TimeUnit unit) //非阻塞式拉取,如果沒(méi)拉取到,會(huì)再等待timeout毫秒,還沒(méi)拉取到才返回null。
總結(jié)
以上所述是小編給大家介紹的Java NIO.2 使用Path接口來(lái)監(jiān)聽(tīng)文件、文件夾變化,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺(jué)得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
Java創(chuàng)建型設(shè)計(jì)模式之單例模式
Java單例模式是一種設(shè)計(jì)模式,它確保一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)全局訪問(wèn)點(diǎn)。可以使用多種方式實(shí)現(xiàn)單例模式,如餓漢式、懶漢式、雙重檢查鎖定、靜態(tài)內(nèi)部類、枚舉等,每種方式都有其優(yōu)缺點(diǎn),需要根據(jù)具體情況選擇使用2023-05-05
HashMap原理及手寫實(shí)現(xiàn)部分區(qū)塊鏈特征
這篇文章主要為大家介紹了HashMap原理及手寫實(shí)現(xiàn)部分區(qū)塊鏈特征,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
java?kafka如何動(dòng)態(tài)設(shè)置用戶讀寫權(quán)限
這篇文章主要介紹了java?kafka如何動(dòng)態(tài)設(shè)置用戶讀寫權(quán)限問(wèn)題,具有很好的參考家價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08
System.currentTimeMillis()計(jì)算方式與時(shí)間的單位轉(zhuǎn)換詳解
這篇文章主要介紹了System.currentTimeMillis()計(jì)算方式與時(shí)間的單位轉(zhuǎn)換詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05
詳解如何快速定位和解決JSON錯(cuò)誤(以Protobuf的JsonFormat.ParseException為例)
在開(kāi)發(fā)過(guò)程中,JSON數(shù)據(jù)的解析是一個(gè)常見(jiàn)的操作,尤其是在微服務(wù)架構(gòu)中,服務(wù)之間的通信通常依賴于JSON格式的數(shù)據(jù),然而,JSON數(shù)據(jù)的格式錯(cuò)誤往往會(huì)導(dǎo)致解析失敗,進(jìn)而引發(fā)系統(tǒng)異常,本文將以一個(gè)實(shí)際的錯(cuò)誤案例為例,詳細(xì)講解如何快速定位和解決JSON解析錯(cuò)誤2025-03-03
Springboot3整合Mybatis-plus3.5.3報(bào)錯(cuò)問(wèn)題解決
在日常學(xué)習(xí)springboot3相關(guān)的代碼時(shí),在使用 SpringBoot3 整合 MyBatisplus 時(shí)出現(xiàn)了一些問(wèn)題,花了不少時(shí)間處理,這篇文章主要介紹了Springboot3整合Mybatis-plus3.5.3報(bào)錯(cuò)問(wèn)題解決,需要的朋友可以參考下2023-11-11
淺談一下SpringCloud中Hystrix服務(wù)熔斷和降級(jí)原理
這篇文章主要介紹了淺談一下SpringCloud中Hystrix服務(wù)熔斷和降級(jí)原理,Hystrix 是 Netflix 的一款開(kāi)源的容錯(cuò)框架,通過(guò)服務(wù)隔離來(lái)避免由于依賴延遲、異常,引起資源耗盡導(dǎo)致系統(tǒng)不可用的解決方案,需要的朋友可以參考下2023-05-05

