File IO(NIO.2):文件操作

簡介

Files類是java.nio.file包的另一個主要入口點。該類提供了一組豐富的靜態方法,用於讀取,寫入和操作文件和目錄。Files方法適用於Path對象的實例。在進行其餘部分之前,您應該熟悉以下常見概念:釋放系統資源、捕捉異常、可變參數、原子操作、方法鏈、什麼是Glob

釋放系統資源

此API中使用的許多資源(如流或通道)實現或擴展了java.io.Closeable接口。關閉資源的要求是必須調用close方法以在不再需要時釋放資源。忽略關閉資源可能會對應用程序的性能產生負面影響。下一節中描述的try-with-resources語句爲您處理此步驟。

捕捉異常

使用文件I / O,一個很現實很常見的意外是:當一個文件被期待時,它存在(或不存在),該程序無法訪問該文件系統,默認文件系統實現不支持特定功能,等等。可能會遇到許多錯誤。

訪問文件系統的所有方法都可能會導致IOException異常。最好的做法是通過將這些方法嵌入到Java SE 7版本中引入的try-with-resources語句中來捕獲這些異常。try-with-resources語句的優點在於,當不再需要時,編譯器會自動生成代碼以關閉資源。以下代碼顯示瞭如何顯示:

Charset charset = Charset.forName("US-ASCII");
String s = ...;
try (BufferedWriter writer = Files.newBufferedWriter(file, charset)) {
    writer.write(s, 0, s.length());
} catch (IOException x) {
    System.err.format("IOException: %s%n", x);
}
或者,您可以將文件I / O方法嵌入到try塊中,然後捕獲catch塊中的任何異常。如果你的代碼打開了任何流或通道,你應該在一個finally塊中關閉它們。前面的例子看起來像以下使用try-catch-finally方法:
Charset charset = Charset.forName("US-ASCII");
String s = ...;
BufferedWriter writer = null;
try {
    writer = Files.newBufferedWriter(file, charset);
    writer.write(s, 0, s.length());
} catch (IOException x) {
    System.err.format("IOException: %s%n", x);
} finally {
    if (writer != null) writer.close();
}
除了IOException之外,很多具體的異常擴展了FileSystemException。這個類有一些有用的方法返回涉及的文件(getFile),詳細的消息字符串(getMessage)文件系統操作失敗(getReason)和“其他”文件涉及的原因(如果有的話)(getOtherFile)

以下代碼片段顯示瞭如何使用getFile方法

try (...) {
    ...    
} catch (NoSuchFileException x) {
    System.err.format("%s does not exist\n", x.getFile());
}
爲了清楚起見,本課程中的文件I / O示例可能不會顯示異常處理,但是您的代碼應該始終包含它

可變參數

當指定標誌時,幾個Files方法接受任意數量的參數。例如,在以下方法簽名中,CopyOption參數之後的橢圓符號表示該方法接受可變數量的參數或變量,因爲它們通常稱爲:

Path Files.move(Path, Path, CopyOption...)
就像move的例子,可以向下面一樣被調用:

import static java.nio.file.StandardCopyOption.*;

Path source = ...;
Path target = ...;
Files.move(source,
           target,
           REPLACE_EXISTING,
           ATOMIC_MOVE);

原子操作

幾個Files方法,比如move,在一些文件系統中可以進行原子操作

一個原子操作的含義是:操作不能被中斷或者部分執行。 不管是進入操作失敗還是其他操作失敗,當您有多個進程在文件系統的相同區域運行時,這很重要,您需要確保每個進程訪問完整的文件。

方法鏈

很多文件IO方法都支持方法鏈的概念

你可以首先調用一個方法返回一個對象,然後立刻在這個對象上調用另外一個方法,然後返回另一個操作對象,以此類推。很多IO例子使用下面的技術:

String value = Charset.defaultCharset().decode(buf).toString();
UserPrincipal group =
    file.getFileSystem().getUserPrincipalLookupService().
         lookupPrincipalByName("me");
這個技術提供了一段緊湊的代碼,使你可以避免聲明你不需要的臨時變量

什麼是 Glob?

在File類中,有兩個方法支持接收全局參數,但是,什麼是全局?

您可以使用glob語法指定模式匹配行爲

glob模式被指定爲字符串,並與其他字符串匹配,例如目錄或文件名。 Glob語法遵循幾個簡單的規則:

1,一個星號*匹配任意數量的字符(包括無)。 

2,兩個星號**,像*一樣工作,但跨越目錄邊界。這種語法通常用於匹配完整的路徑。 

3,問號,匹配一個字符。 

4,大括號指定子模式的集合。例如: {太陽,​​月亮,星星}匹配“太陽”,“月亮”或“星星”。 {temp *,tmp *}匹配以“temp”或“tmp”開頭的所有字符串。 

5,方括號傳送一組單個字符,或者使用連字符( - )時,會顯示一系列字符。例如: [aeiou]匹配任何小寫的元音。 [0-9]匹配任何數字。 [A-Z]匹配任何大寫字母。 [a-z,A-Z]匹配任何大寫或小寫字母。 在方括號內,*,?和\匹配自己。 所有其他角色都與自己匹配 

6,要匹配*,?或其他特殊字符,您可以使用反斜槓字符\來將其轉義。例如:\\匹配單個反斜槓,\?匹配問號。

以下是glob語法的一些示例:

* .html - 匹配以.html結尾的所有字符串

 ??? - 匹配三個字母或數字的所有字符串 

* [0-9] * - 匹配包含數值的所有字符串 

* {htm,html,pdf} - 匹配以.htm,.html或.pdf結尾的任何字符串 

a?*。java - 匹配以a開頭的任何字符串,後跟至少一個字母或數字,以.java結尾 

{foo *,* [0-9] *} - 匹配以foo開頭的任何字符串或包含數值的任何字符串 

注意:如果您在鍵盤上鍵入glob模式,並且包含其中一個特殊字符,則必須將模式置於引號(“*”)中,使用反斜槓(\ *),或使用任何支持的轉義機制命令行。 

glob語法功能強大且易於使用。但是,如果您的需求不足,您還可以使用正則表達式。有關更多信息,請參閱正則表達式課程。 有關glob sytnax的更多信息,請參閱FileSystem類中的getPathMatcher方法的API規範。


發佈了306 篇原創文章 · 獲贊 230 · 訪問量 57萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章