天天看點

Java8的NIO新檔案I/O到底有多好用?(中)目錄路徑監聽

目錄

Files 工具類包含大部分我們需要的目錄操作和檔案操作方法。出于某種原因,它們沒有包含删除目錄樹相關的方法

Java8的NIO新檔案I/O到底有多好用?(中)目錄路徑監聽

删除目錄樹的方法實作依賴于 Files.walkFileTree(),“walking” 目錄樹意味着周遊每個子目錄和檔案。Visitor 設計模式提供了一種标準機制來通路集合中的每個對象,然後你需要提供在每個對象上執行的操作。

此操作的定義取決于實作的 FileVisitor 的四個抽象方法,包括:

preVisitDirectory()

Java8的NIO新檔案I/O到底有多好用?(中)目錄路徑監聽
  • 在通路目錄中條目之前在目錄上運作。
  • visitFile():調用目錄中的檔案
  • Java8的NIO新檔案I/O到底有多好用?(中)目錄路徑監聽
  • visitFileFailed()
  • Java8的NIO新檔案I/O到底有多好用?(中)目錄路徑監聽
  • 調用無法被通路的檔案。如果該檔案的屬性不能被讀取,該檔案是無法打開一個目錄,以及其他原因,該方法被調用。
  • postVisitDirectory()

    在通路目錄中條目之後在目錄上運作,包括所有的子目錄。

  • Java8的NIO新檔案I/O到底有多好用?(中)目錄路徑監聽
  • 為了簡化,java.nio.file.SimpleFileVisitor 提供了所有方法的預設實作
  • Java8的NIO新檔案I/O到底有多好用?(中)目錄路徑監聽
  • 在自己的匿名内部類中,隻需要重寫非标準行為的方法:visitFile() 和 postVisitDirectory() 實作删除檔案和删除目錄。兩者都應該傳回标志位決定是否繼續通路

作為探索目錄操作的一部分,現在我們可以有條件地删除已存在的目錄。在以下例子中,makeVariant() 接受基本目錄測試,并通過旋轉部件清單生成不同的子目錄路徑。這些旋轉與路徑分隔符 sep 使用 String.join() 貼在一起,然後傳回一個 Path 對象。

如果你對于已經存在的目錄調用 createDirectory() 将會抛出異常。createFile() 使用參數 Path 建立一個空檔案; resolve() 将檔案名添加到 test Path 的末尾。

我們嘗試使用 createDirectory() 來建立多級路徑,但是這樣會抛出異常,因為這個方法隻能建立單級路徑。我已經将 populateTestDir() 作為一個單獨的方法,因為它将在後面的例子中被重用。對于每一個變量 variant,我們都能使用 createDirectories() 建立完整的目錄路徑,然後使用此檔案的副本以不同的目标名稱填充該終端目錄。然後我們使用 createTempFile() 生成一個臨時檔案。

在調用 populateTestDir() 之後,我們在 test 目錄下面下面建立一個臨時目錄。請注意,createTempDirectory() 隻有名稱的字首選項。與 createTempFile() 不同,我們再次使用它将臨時檔案放入新的臨時目錄中。你可以從輸出中看到,如果未指定字尾,它将預設使用".tmp"作為字尾。

為了展示結果,我們首次使用看起來很有希望的 newDirectoryStream(),但事實證明這個方法隻是傳回 test 目錄内容的 Stream 流,并沒有更多的内容。要擷取目錄樹的全部内容的流,請使用 Files.walk()。

檔案系統

為了完整起見,我們需要一種方法查找檔案系統相關的其他資訊。在這裡,我們使用靜态的 FileSystems 工具類擷取"預設"的檔案系統,但也可以在 Path 對象上調用 getFileSystem() 以擷取建立該 Path 的檔案系統。

可以獲得給定 URI 的檔案系統,還可以建構新的檔案系統(對于支援它的作業系統)。

Java8的NIO新檔案I/O到底有多好用?(中)目錄路徑監聽
Java8的NIO新檔案I/O到底有多好用?(中)目錄路徑監聽

路徑監聽

通過 WatchService 可以設定一個程序對目錄中的更改做出響應。

一旦我們從 FileSystem 中得到了 WatchService 對象,我們将其注冊到 test 路徑以及我們感興趣的項目的變量參數清單中,可以選擇

ENTRY_CREATE

Java8的NIO新檔案I/O到底有多好用?(中)目錄路徑監聽

ENTRY_DELETE

Java8的NIO新檔案I/O到底有多好用?(中)目錄路徑監聽

ENTRY_MODIFY(其中建立和删除不屬于修改)。

Java8的NIO新檔案I/O到底有多好用?(中)目錄路徑監聽

接下來對 watcher.take() 的調用會在發生某些事情之前停止所有操作,是以我們希望 deltxtfiles() 能夠并行運作以便生成我們感興趣的事件。為了實作這個目的,通過調用 Executors.newSingleThreadScheduledExecutor() 産生一個 ScheduledExecutorService 對象,然後調用 schedule() 方法傳遞所需函數的方法引用,并且設定在運作之前應該等待的時間。

此時,watcher.take() 将等待并阻塞在這裡。當目标事件發生時,會傳回一個包含 WatchEvent 的 Watchkey 對象。

如果說"監視這個目錄",自然會包含整個目錄和下面子目錄,但實際上的:隻會監視給定的目錄,而不是下面的所有内容。如果需要監視整個樹目錄,必須在整個樹的每個子目錄上放置一個 Watchservice。