目錄
Files 工具類包含大部分我們需要的目錄操作和檔案操作方法。出于某種原因,它們沒有包含删除目錄樹相關的方法
删除目錄樹的方法實作依賴于 Files.walkFileTree(),“walking” 目錄樹意味着周遊每個子目錄和檔案。Visitor 設計模式提供了一種标準機制來通路集合中的每個對象,然後你需要提供在每個對象上執行的操作。
此操作的定義取決于實作的 FileVisitor 的四個抽象方法,包括:
preVisitDirectory()
- 在通路目錄中條目之前在目錄上運作。
- visitFile():調用目錄中的檔案
- visitFileFailed()
- 調用無法被通路的檔案。如果該檔案的屬性不能被讀取,該檔案是無法打開一個目錄,以及其他原因,該方法被調用。
-
postVisitDirectory()
在通路目錄中條目之後在目錄上運作,包括所有的子目錄。
- 為了簡化,java.nio.file.SimpleFileVisitor 提供了所有方法的預設實作
- 在自己的匿名内部類中,隻需要重寫非标準行為的方法: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 的檔案系統,還可以建構新的檔案系統(對于支援它的作業系統)。
路徑監聽
通過 WatchService 可以設定一個程序對目錄中的更改做出響應。
一旦我們從 FileSystem 中得到了 WatchService 對象,我們将其注冊到 test 路徑以及我們感興趣的項目的變量參數清單中,可以選擇
ENTRY_CREATE
ENTRY_DELETE
ENTRY_MODIFY(其中建立和删除不屬于修改)。
接下來對 watcher.take() 的調用會在發生某些事情之前停止所有操作,是以我們希望 deltxtfiles() 能夠并行運作以便生成我們感興趣的事件。為了實作這個目的,通過調用 Executors.newSingleThreadScheduledExecutor() 産生一個 ScheduledExecutorService 對象,然後調用 schedule() 方法傳遞所需函數的方法引用,并且設定在運作之前應該等待的時間。
此時,watcher.take() 将等待并阻塞在這裡。當目标事件發生時,會傳回一個包含 WatchEvent 的 Watchkey 對象。
如果說"監視這個目錄",自然會包含整個目錄和下面子目錄,但實際上的:隻會監視給定的目錄,而不是下面的所有内容。如果需要監視整個樹目錄,必須在整個樹的每個子目錄上放置一個 Watchservice。