Java7對(duì)NIO進(jìn)行了大的改進(jìn),新增了許多功能:
創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供遵化網(wǎng)站建設(shè)、遵化做網(wǎng)站、遵化網(wǎng)站設(shè)計(jì)、遵化網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、遵化企業(yè)網(wǎng)站模板建站服務(wù),十余年遵化做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。
•對(duì)文件系統(tǒng)的訪問提供了全面的支持
•提供了基于異步Channel的IO
這些新增的IO功能簡(jiǎn)稱為 NIO.2,依然在java.nio包下。
早期的Java只提供了File類來操作文件、文件夾本身,功能有限,性能也不高。
NIO.2為解決這種缺陷,提供了Path接口,并提供了Paths、Files2個(gè)工具類,這2個(gè)工具類包含的方法都是靜態(tài)方法,F(xiàn)iles類提供了大量的靜態(tà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ì)象中的路徑,就是說路徑不必是真實(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è)方法來監(jiān)聽文件變化:
register(WatchService watcher, 要監(jiān)聽的事件類型1,要監(jiān)聽的事件類型2,.......) //注冊(cè)一個(gè)監(jiān)聽服務(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)聽服務(wù) WatchService watchService= FileSystems.getDefault().newWatchService(); Path path=Paths.get("D:/untitled/test"); //為該文件夾注冊(cè)監(jiān)聽,監(jiān)聽新建、修改、刪除事件。只能為文件夾(目錄)注冊(cè)監(jiān)聽,不能為單個(gè)文件注冊(cè)監(jiān)聽 path.register(watchService,StandardWatchEventKinds.ENTRY_CREATE,StandardWatchEventKinds.ENTRY_MODIFY,StandardWatchEventKinds.ENTRY_DELETE); //編寫事件處理 while (true){ //一直監(jiān)聽 //拉取一個(gè)WatchKey。當(dāng)觸發(fā)監(jiān)聽的事件時(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)聽,如果要監(jiān)聽某些指定的文件,可以在增強(qiáng)的for循環(huán)中,先根據(jù)event.context()判斷是否是指定的文件,是才處理。 */ } //雖然是while()循環(huán),但WatchKey和ByteBuffer一樣,使用完要重置狀態(tài),才能繼續(xù)用。 watchKey.reset(); //如果不重置,WatchKey使用一次過后就不能再使用,即只能監(jiān)聽到一次文件變化。 } /* 測(cè)試:在D:/untitled/test目錄下 1、新建1.txt文件 1.txt.txt發(fā)生了ENTRY_CREATE事件! 2、打開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事件! 說明:編輯文件內(nèi)容時(shí),不算修改,保存時(shí)才算修改。 5、新建文件夾“圖片” 新建文件夾發(fā)生了ENTRY_CREATE事件! 新建文件夾發(fā)生了ENTRY_DELETE事件! 圖片發(fā)生了ENTRY_CREATE事件! OS執(zhí)行過程:新建了一個(gè)名為“新建文件夾”的文件夾,再把此文件夾重命名為指定的名稱。 重命名時(shí),”新建文件夾“消失了,算作刪除,”圖片“出現(xiàn)了,算作新建。 6、在圖片目錄下,隨便新建一個(gè)文件或者文件夾 圖片發(fā)生了ENTRY_MODIFY事件! 說明監(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ì)象,沒有WatchKey發(fā)生就立即返回null。
•WatchKey poll(long timeout, TimeUnit unit) //非阻塞式拉取,如果沒拉取到,會(huì)再等待timeout毫秒,還沒拉取到才返回null。
總結(jié)
以上所述是小編給大家介紹的Java NIO.2 使用Path接口來監(jiān)聽文件、文件夾變化,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)創(chuàng)新互聯(lián)網(wǎng)站的支持!
如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!