Java7 新特性 —— java.nio.file 檔案操作
阿新 • • 發佈:2020-11-17
> 本文部分摘自 On Java 8
自 Java7 開始,Java 終於簡化了檔案讀寫的基本操作,新增了 java.nio.file 庫,通過與 Java8 新增的 stream 結合可以使得檔案操作變得更加優雅
## 檔案和目錄路徑 java.nio.file.Paths 類包含一個過載方法 static.get(),可以接受一系列 String 字串或一個統一資源識別符號 URI 作為引數,並且轉換返回一個 Paths 物件。使用 Paths 物件可以很輕鬆地生成路徑的某一部分: ```java Path path1 = Paths.get("C:", "path", "to", "nowhere", "NoFile.txt"); Path path2 = Paths.get("C:/path/to/nowhere/NoFile.txt"); URI uri = path2.toUri(); Path3 path3 = Paths.get(uri); ``` 一個 Path 物件表示一個檔案或者目錄的路徑,是一個跨作業系統和檔案系統的抽象,目的是在構造路徑時可以不必關注底層作業系統。如果 Path 僅由一個空的名稱元素組成,則認為是空的路徑。使用空路徑訪問檔案等同於訪問檔案系統的預設目錄。Path 介面的實現是不可變且安全的,可供多個並行執行緒使用 使用 Path 物件可以非常容易地生成路徑的某一部分: ```java // 返回表示此路徑的絕對路徑的Path物件 Path p = Paths.get("PartsOfPaths.java").toAbsolutePath(); // 返回表示此路徑的真實路徑的Path物件,也即是帶上碟符(根路徑) Path p2 = Paths.get("PartsOfPaths.java").toRealPath(); // getNameCount() 返回路徑中的名稱元素的數量 // 例如 p 的絕對路徑是 C:\User\Bruce\Documents\GitHub\PartsOfPaths.java // 則此迴圈會依次輸出 User、Bruce、Documents、PartsOfPaths.java for(int i = 0; i < p.getNameCount(); i++) { // 返回此路徑的名稱元素作為 Path物件 System.out.println(p.getName(i)); } // 測試路徑是否以給定的路徑結束,這裡會輸出 end with '.java':false System.out.println("ends with '.java': " + p.endsWith(".java")); // Path 也實現了 iterable 介面,會對路徑中的名稱元素進行遍歷 for(Path pp : p) { ... } // getRoot() 返回此路徑的根路徑作為Path物件,為null則該路徑不具有根 // startsWith() 效果和 endsWith() 相似 // 這裡會輸出 Starts with C:\ true System.out.println("Starts with " + p.getRoot() + " " + p.startsWith(p.getRoot())); ``` 有時我們還需要通過對 Path 物件增加或修改一部分來構造一個新的 path 物件,可以使用 relativize() 移除 Path 的根路徑,或者使用 resolve() 新增 Path 的尾路徑,注意新增的路徑可以不是真實存在的 ``` java // 使用..可以跳轉到上一級路徑,但必須使用normalize()方法 // 假設當前路徑為C:\Users\Bruce\Documents\GitHub\PartsOfPaths.java,則輸出C:\Users Path base = Paths.get("..", "..", "..").toAbsolutePath().normalize(); // 返回表示此路徑的絕對路徑的Path物件 Path p = Paths.get("PartsOfPaths.java").toAbsolutePath(); // 構造此路徑和給定路徑之間的相對路徑 Path p2 = base.relativize(p); // 使用resolve構造路徑 // 此時路徑為C:\Users\Bruce\Documents\GitHub\string Path convoluted = p.getParent().resolve("string"); ``` 有關 Path 的更多用法,可以查閱 Java API 瞭解更多資訊
## 檔案查詢與讀寫 我們可以通過在 FileSystem 物件上呼叫 getPathMatcher() 獲得一個 PathMatcher,然後傳入你感興趣的模式。模式有兩個選項:glob 和 regex,glob 比較簡單,功能也很強大,這裡主要介紹 glob ```java Path test = Paths.get("test"); // 查詢當前目錄及其子目錄下所有以.tmp或.txt結尾的Path // **/表示當前目錄及其所有子目錄 // * 表示任何字元,大括號表示一系列的可能性 PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:**/*.{tmp,txt}"); Files.walk(test).filter(matcher::matches).forEach(System.out::println); ``` 找到檔案之後,我們就可以對路徑和目錄做任何事情。如果一個檔案很小,那麼 java.nio.file.Files 類中的方法可以幫助你輕鬆地讀寫文字和二進位制檔案 使用 Files.readAllLines() 方法可以一次讀取整個檔案,產出一個 List\