java流与文件——操作文件
【0】README
0.1) 本文描述轉自 core java volume 2, 旨在理解 java流與文件——操作文件 的相關知識;
0.2) for source code, please visit https://github.com/pacosonTang/core-java-volume/blob/master/coreJavaAdvanced/chapter1/FileAndPathTest.java)
【1】Path
1.1)Path: 表示的是一個目錄名序列, 其后還可以跟一個文件名;路徑中的第一個部件可以是跟部件, 例如 / 或 C:/ , 而有序訪問的根部件,取決于文件系統;(干貨——Path類定義)
- 1.1.1)以根目錄開始的是絕對路徑,否則就是相對路徑;如,
Path absolute = Paths.get(“/home”, “cay”);
Path relative = Paths.get(“myprog”, “cay”); - 1.1.2) 靜態的 Paths.get 方法: 接受一個或多個字符串, 并將它們用默認文件系統的路徑分隔符連接起來;
- 1.1.3)get方法: 可以獲取包含多個部件構成的單個字符串, 如, 可以像下面這樣從配置文件中讀取路徑:
String baseDir = props.getProperty(“base.dir”);
Path basePath = Paths.get(baseDir);
Attention)
- A1)路徑不必對應著某個實際存在的文件, 他僅僅只是一個抽象的名字序列;
- A2)當你想要創建文件時, 首先要創建一個路徑,然后才調用方法去創建對應的文件;
1.2)組合或解析路徑是司空見慣的操作,調用 p.resolve(q) 將按照下列規則返回一個路徑: (干貨——p后面跟著q)
- 1.2.1)如果 q 是絕對路徑, 則結果就是q;
- 1.2.2)否則,根據文件系統的規則, 將p 后面跟著q 作為結果;
1.2.3) resolve 方法有一種快捷方式,它接收一個字符串而不是路徑:
Path workPath = basePath.resolve(“work”);1.2.4)還有一個 方法: resolveSibling
它通過解析指定路徑的父路徑產生其兄弟路徑, 例如, 如果workPath 是 /opt/myapp/work, 那么下面的調用
Path tempPath = workPath.resolveSibling(“temp”) 將創建 /opt/myapp/temp; (干貨——創建兄弟路徑)- 1.2.5)resolve的對立面是 relative: 即調用 p.relativeze(r) 將產生路徑q, 對q進行解鎖產生r;
- 1.2.6)normalize 方法:移除所有冗余的 . 和 .. 部件(或者文件系統認為冗余的所有部件);
如規范化 /home/cay/../fred/./ myprog 將產生 /home/fred/myprog
- 1.2.7)toAbsolutePath 方法: 將產生給定路徑的絕對路徑, 該絕對路徑從根部件開始;
1.2.8) Path類有許多方法用來將路徑斷開以及和其它路徑進行組合。如:
Path p = Paths.get(“/home”, “myprog.properties”);
Path parent = p.getParent();
Path file = p.getFilename();
Path root = p.getRoot();Attention) 你可能需要與遺留系統的API 交互, 它們使用的是 File 類而不是 Path 類。 Path類有一個toFile 方法, 而 File 類也有一個 toPath 方法;
【2】讀寫文件
2.1)Files 類可以使得普通文件操作變得快捷;
- 2.1.1)用下面的方式很容易的讀取文件的所有內容:
byte[] bytes = Files.readAllBytes(path); - 2.1.2)如果想將文件當做字符串輸入, 則:
String content = enw String(bytes, charset); - 2.1.3)如果希望 將文件當做行序列輸入, 則:
List lines = Files.readAllLines(path, charset); - 2.1.4)相反地, 如果希望寫出一個字符串到文件中, 則:
Files.write(path, content.getBytes(charset));
- 2.1.5)向指定文件追加內容,則:
Files.write(path, content.getBytes(charset), StandardOpoenOption.APPEND); - 2.1.6)還可以用下面的語句將一行集合寫出到文件中:
Files.write(path, lines);
2.1.7) 如果要處理的文件長度過大, 或者是二進制文件, 那么還是應該使用所熟悉的流或者讀入器/ 寫出器;
InputStream is = Files.newInputStream(path);
OutputStream os = Files.newOutputStream(path);
Reader reader = Files.newBufferedReader(path, charset);
Writer writer = Files.newBufferedWriter(path, charset);2.1.8)總結: 這些便捷方法可以將你從處理 FileInputStream, FileInputStream, BufferedReader 和 BufferedWriter 的繁復操作中解脫出來;
【3】復制、移動和刪除文件
3.1)復制文件: Files.copy(fromPath, toPath);
3.2)移動文件 (復制并刪除源文件): Files.move(frompath, topath);
- 3.2.1)如果目標路徑已經存在,那么復制或移動將失敗;
- 3.2.2)如果想要覆蓋已有的目標路徑, 可以使用 REPLACE_EXISTING 選項;
- 3.2.3)如果想要復制文件的屬性, 可以使用 COPY_ATTRIBUTES ;
- 3.2.4)也可以同時使用者兩個選項:
Files.copy(fromPath, toPath, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES); - 3.2.5)可以將移動操作定義為 原子性的(要么全部成功, 要么就不成功)
Files.move(fromPath, toPath, StandardCopyOption.ATOMIC_MOVE); - 3.2.6)最后刪除文件,調用:
Files.delete(path); - 3.2.7)如果要刪除的文件不存在, delete 方法就會拋出異常;使用 deleteIfExists 不會拋出異常,
boolean deleted = Files.deleteIfExists(path); 該方法 deleteIfExists 還可以用來移除空目錄;
【4】 創建文件和目錄
4.1)創建目錄: Files.createDirectory(path);
4.2)創建中間目錄: Files.createDirectories(path); (迭代創建目錄)
- 4.2.1)創建空文件: Files.createFile(path)
- 4.2.2)有些便捷方法用來在給定位置或系統指定位置創建臨時文件或 臨時目錄:
Path newPath = FIles.createTempFile(dir, prefix, suffix);
Path newPath = FIles.createTempFile( prefix, suffix);
Path newPath = FIles.createTempFile(dir, prefix);
Path newPath = FIles.createTempFile(prefix); - 其中,dir 是一個Paht對象,prefix 和 suffix 是可以為 null 的字符串;例如,調用 Files.createTempFile(null, “.txt”) 可能返回一個像 /tmp/2345646464646464.txt這樣的路徑;
【5】 獲取文件信息
5.1)下面的靜態方法都將返回一個boolean值, 表示檢查路徑的某個屬性的結果:
exists + isHidden + isReadable + isWritable + isExecutable + isRegularFile + isDirectory + isSymbolicLink
5.2)size 方法將返回文件的字節數:
long size = Files.size(path);
5.3)getOwner: 將文件的所有者作為 java.nio.file.attribute.UserPrincipal 的一個實例返回;
5.4)所有的文件系統都會報告一個基本屬性集, 它們被封裝在 BasicFileAttributes 接口中, 這些屬性與上述信息有部分重疊。基本文件屬性包括:
- 5.4.1)創建文件, 最后一次訪問以及最后一次修改時間;
- 5.4.2)文件時常規文件, 目錄還是符號鏈接, 或者都不是;
- 5.4.3)文件大小;
- 5.4.4)文件主鍵, 這是某種類的對象, 具體所屬類與文件系統相關, 有可能是文件的唯一標識符,也有可能不是;
- 5.4.5)要獲取這些屬性,調用
BasicFileAttributes attributes = files.readAttributes(path, BasicFileAttributes.class);
5.5) 如果你了解到用戶的文件系統兼容 POSIX, 可以獲取一個 PosiXFileAttributes 實例:
PosiXFileAttributes attributes = files.readAttributes(path, PosiXFileAttributes.class);
然后從中找到組擁有者, 擁有者,組,以及訪問權限;
【6】 迭代目錄中的文件
6.1)problem+solution
- 6.1.1)problem: 舊File 類有一個方法,用來獲取由一個目錄的所有文件構成的數組, 當目錄包含大量的文件時,方法性能非常低;
- 6.1.2)solution: File類設計了一個方法, 產生一個 Iterable 對象, 如:
try(DirectoryStream entries = Files.newDirectoryStream(dir))
{
for(Path entry : entries)
process entries
} - 6.1.3)try 語句塊用來確保目錄流可以被正確關閉。訪問目錄中的項并沒有具體的順序, 可以用 glob 模式來過濾:(干貨——帶資源的try語句塊)
try(DirectoryStream entries = Files.newDirectoryStream(dir, “*.java”));
- Warning)如果使用 Windows 的 glob 語法, 則必須對反斜杠轉移兩次:一次為 glob 語法轉義, 一次為java 字符串轉義:Files.newDirectoryStream(dir, “C:\\”)
6.2)如果想要訪問某個目錄的子孫成員, 轉而調用 walkFileTree 方法, 并向其傳遞一個 FileVisitor 類型的對象, 這個對象會得到下面通知:
- 6.2.1)在遇到一個文件或目錄時: FileVisitResult visitFile(T path, BasicFileAttributes attrs)
- 6.2.2) 在一個目錄被處理前: FileVisitResult preVisitFile(T dir, IOException ex)
- 6.2.3) 在一個目錄被處理后: FileVisitResult postVisitFile(T dir, IOException ex)
- 6.2.4) 在試圖訪問文件或目錄時發生錯誤, 例如沒有權限打開目錄: FileVisitResult visitFileFailed(path, IOException)
6.3) 對上述每種情況, 都可以指定是否希望執行下面的操作:
- 6.3.1)繼續訪問下一個文件: FileVisitResult.CONTINUE;
- 6.3.2)繼續訪問,但不在訪問這個目錄下的任何項了: FileVisitResult.SKIP_SUBTREE;
- 6.3.3)繼續訪問, 但是不在訪問這個文件的兄弟文了: FileVisitResult.SKIP_SIBLINES;
- 6.3.4)終止訪問: FileVisitResult.TRIMINATE ;
6.4) 當有任何方法拋出異常時, 就會終止訪問, 而這個異常會從 walkFileTree 方法中拋出;
- Attention) FileVisitor 接口是泛化類型, 但是你也太可能會使用 除開 FileVisit 之外的東西; walkFileTree 方法可以接收 FileVisitor
【7】 ZIP 文件系統
7.1)建立一個文件系統, 包含 ZIP 文檔中的所有文件;
FileSystem fs = FileSystems.newFIleSystem(Paths.get(zipname), null);
- 7.1.1)如果知道文件名,從ZIP 文檔中復制出這個文件就變得很容易:
Files.copy(fs.getPath(sourceName), targetPath); - 7.1.2)要列出ZIP 文檔中的所有文件, 可以遍歷文件樹:
總結
以上是生活随笔為你收集整理的java流与文件——操作文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 万网的数据库怎么导入(万网的数据库怎么导
- 下一篇: 云服务器怎么设置域名(云服务器怎么设置域