Java NIO 教程(十五) Java NIO Files

原文地址

目錄

Java NIO Files類(java.nio.file.Files)提供了幾種操作文件系統中的文件的方法。這個Java NIO Files教程將介紹最常用的這些方法。Files類包含許多方法,所以如果您需要一個在這里沒有描述的方法,那么請檢查JavaDoc。Files類可能還會有一個方法來實現它。

java.nio.file.Files類與java.nio.file.Path實例一起工作,因此在處理Files類之前,您需要了解Path類。

Files.exists()

Files.exists()方法檢查給定的Path在文件系統中是否存在。

可以創建在文件系統中不存在的Path實例。例如,如果您計劃創建一個新目錄,您首先要創建相應的Path實例,然后創建目錄。

由于Path實例可能指向,也可能沒有指向文件系統中存在的路徑,你可以使用Files.exists()方法來確定它們是否存在(如果需要檢查的話)。

這里是一個Java Files.exists()的例子:

Path path = Paths.get("data/logging.properties");

boolean pathExists =
        Files.exists(path,
            new LinkOption[]{ LinkOption.NOFOLLOW_LINKS});

這個例子首先創建一個Path實例指向一個路徑,我們想要檢查這個路徑是否存在。然后,這個例子調用Files.exists()方法,然后將Path實例作為第一個參數。

注意Files.exists()方法的第二個參數。這個參數是一個選項數組,它影響Files.exists()如何確定路徑是否存在。在上面的例子中的數組包含LinkOption.NOFOLLOW_LINKS,這意味著Files.exists()方法不應該在文件系統中跟蹤符號鏈接,以確定文件是否存在。

Files.createDirectory()

Files.createDirectory()方法,用于根據Path實例創建一個新目錄,下面是一個Files.createDirectory()例子:

Path path = Paths.get("data/subdir");

try {
    Path newDir = Files.createDirectory(path);
} catch(FileAlreadyExistsException e){
    // 目錄已經存在
} catch (IOException e) {
    // 其他發生的異常
    e.printStackTrace();
}

第一行創建表示要創建的目錄的Path實例。在try-catch塊中,用路徑作為參數調用Files.createDirectory()方法。如果創建目錄成功,將返回一個Path實例,該實例指向新創建的路徑。

如果該目錄已經存在,則是拋出一個java.nio.file.FileAlreadyExistsException。如果出現其他錯誤,可能會拋出IOException。例如,如果想要的新目錄的父目錄不存在,則可能會拋出IOException。父目錄是您想要創建新目錄的目錄。因此,它表示新目錄的父目錄。

Files.copy()

Files.copy()方法從一個路徑拷貝一個文件到另外一個目錄,這里是一個Java Files.copy()例子:

Path sourcePath      = Paths.get("data/logging.properties");
Path destinationPath = Paths.get("data/logging-copy.properties");

try {
    Files.copy(sourcePath, destinationPath);
} catch(FileAlreadyExistsException e) {
    // 目錄已經存在
} catch (IOException e) {
    // 其他發生的異常
    e.printStackTrace();
}

首先,該示例創建一個源和目標Path實例。然后,這個例子調用Files.copy(),將兩個Path實例作為參數傳遞。這可以讓源路徑引用的文件被復制到目標路徑引用的文件中。

如果目標文件已經存在,則拋出一個java.nio.file.FileAlreadyExistsException異常。如果有其他錯誤,則會拋出一個IOException。例如,如果將該文件復制到不存在的目錄,則會拋出IOException

重寫已存在的文件

可以強制Files.copy()覆蓋現有的文件。這里有一個示例,演示如何使用Files.copy()覆蓋現有文件。

Path sourcePath      = Paths.get("data/logging.properties");
Path destinationPath = Paths.get("data/logging-copy.properties");

try {
    Files.copy(sourcePath, destinationPath,
            StandardCopyOption.REPLACE_EXISTING);
} catch(FileAlreadyExistsException e) {
    // 目標文件已存在
} catch (IOException e) {
    // 其他發生的異常
    e.printStackTrace();
}

請注意Files.copy()方法的第三個參數。如果目標文件已經存在,這個參數指示copy()方法覆蓋現有的文件。

Files.move()

Java NIO Files還包含一個函數,用于將文件從一個路徑移動到另一個路徑。移動文件與重命名相同,但是移動文件既可以移動到不同的目錄,也可以在相同的操作中更改它的名稱。是的,java.io.File類也可以使用它的renameTo()方法來完成這個操作,但是現在已經在java.nio.file.Files中有了文件移動功能。

這里有一個Java Files.move()例子:

Path sourcePath      = Paths.get("data/logging-copy.properties");
Path destinationPath = Paths.get("data/subdir/logging-moved.properties");

try {
    Files.move(sourcePath, destinationPath,
            StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
    //移動文件失敗
    e.printStackTrace();
}

首先創建源路徑和目標路徑。源路徑指向要移動的文件,而目標路徑指向文件應該移動到的位置。然后調用Files.move()方法。這會導致文件被移動。

請注意傳遞給Files.move()的第三個參數。這個參數告訴Files.move()方法來覆蓋目標路徑上的任何現有文件。這個參數實際上是可選的。

如果移動文件失敗,Files.move()方法可能拋出一個IOException。例如,如果一個文件已經存在于目標路徑中,并且您已經排除了StandardCopyOption.REPLACE_EXISTING選項,或者被移動的文件不存在等等。

Files.delete()

Files.delete()方法可以刪除一個文件或者目錄。下面是一個Java Files.delete()例子:

Path path = Paths.get("data/subdir/logging-moved.properties");

try {
    Files.delete(path);
} catch (IOException e) {
    // 刪除文件失敗
    e.printStackTrace();
}

首先,創建指向要刪除的文件的Path。然后調用Files.delete()方法。如果Files.delete()由于某種原因不能刪除文件(例如,文件或目錄不存在),會拋出一個IOException

Files.walkFileTree()

Files.walkFileTree()方法包含遞歸遍歷目錄樹的功能。walkFileTree()方法將Path實例和FileVisitor作為參數。Path實例指向您想要遍歷的目錄。FileVisitor在遍歷期間被調用。

在我解釋遍歷是如何工作之前,這里我們先了解FileVisitor接口:

public interface FileVisitor {
    public FileVisitResult preVisitDirectory(
        Path dir, BasicFileAttributes attrs) throws IOException;

    public FileVisitResult visitFile(
        Path file, BasicFileAttributes attrs) throws IOException;

    public FileVisitResult visitFileFailed(
        Path file, IOException exc) throws IOException;

    public FileVisitResult postVisitDirectory(
        Path dir, IOException exc) throws IOException {
}

您必須自己實現FileVisitor接口,并將實現的實例傳遞給walkFileTree()方法。在目錄遍歷過程中,您的FileVisitor實現的每個方法都將被調用。如果不需要實現所有這些方法,那么可以擴展SimpleFileVisitor類,它包含FileVisitor接口中所有方法的默認實現。

這里是一個walkFileTree()的例子:

Files.walkFileTree(path, new FileVisitor<Path>() {
  @Override
  public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
    System.out.println("pre visit dir:" + dir);
    return FileVisitResult.CONTINUE;
  }

  @Override
  public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
    System.out.println("visit file: " + file);
    return FileVisitResult.CONTINUE;
  }

  @Override
  public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
    System.out.println("visit file failed: " + file);
    return FileVisitResult.CONTINUE;
  }

  @Override
  public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
    System.out.println("post visit directory: " + dir);
    return FileVisitResult.CONTINUE;
  }
});

FileVisitor實現中的每個方法在遍歷過程中的不同時間都被調用:

在訪問任何目錄之前調用preVisitDirectory()方法。在訪問一個目錄之后調用postVisitDirectory()方法。

調用visitFile()在文件遍歷過程中訪問的每一個文件。它不會訪問目錄-只會訪問文件。在訪問文件失敗時調用visitFileFailed()方法。例如,如果您沒有正確的權限,或者其他什么地方出錯了。

這四個方法中的每個都返回一個FileVisitResult枚舉實例。FileVisitResult枚舉包含以下四個選項:

  • CONTINUE 繼續
  • TERMINATE 終止
  • SKIP_SIBLING 跳過同級
  • SKIP_SUBTREE 跳過子級

通過返回其中一個值,調用方法可以決定如何繼續執行文件。

CONTINUE繼續意味著文件的執行應該像正常一樣繼續。

TERMINATE終止意味著文件遍歷現在應該終止。

SKIP_SIBLINGS跳過同級意味著文件遍歷應該繼續,但不需要訪問該文件或目錄的任何同級。

SKIP_SUBTREE跳過子級意味著文件遍歷應該繼續,但是不需要訪問這個目錄中的子目錄。這個值只有從preVisitDirectory()返回時才是一個函數。如果從任何其他方法返回,它將被解釋為一個CONTINUE繼續。

文件搜索

這里是一個用于擴展SimpleFileVisitorwalkFileTree(),以查找一個名為README.txt的文件:

Path rootPath = Paths.get("data");
String fileToFind = File.separator + "README.txt";

try {
  Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
    
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
      String fileString = file.toAbsolutePath().toString();
      //System.out.println("pathString = " + fileString);

      if(fileString.endsWith(fileToFind)){
        System.out.println("file found at path: " + file.toAbsolutePath());
        return FileVisitResult.TERMINATE;
      }
      return FileVisitResult.CONTINUE;
    }
  });
} catch(IOException e){
    e.printStackTrace();
}

遞歸刪除目錄

Files.walkFileTree()也可以用來刪除包含所有文件和子目錄的目錄。Files.delete()方法只會刪除一個目錄,如果它是空的。通過遍歷所有目錄并刪除每個目錄中的所有文件(在visitFile())中,然后刪除目錄本身(在postVisitDirectory()中),您可以刪除包含所有子目錄和文件的目錄。下面是一個遞歸目錄刪除示例:

Path rootPath = Paths.get("data/to-delete");

try {
  Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
      System.out.println("delete file: " + file.toString());
      Files.delete(file);
      return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
      Files.delete(dir);
      System.out.println("delete dir: " + dir.toString());
      return FileVisitResult.CONTINUE;
    }
  });
} catch(IOException e){
  e.printStackTrace();
}

文件類中的其他方法

java.nio.file.Files類包含許多其他有用的函數,比如用于創建符號鏈接的函數、確定文件大小、設置文件權限等等。有關這些方法的更多信息,請查看java.nio.file.Files類的JavaDoc。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,935評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,908評論 2 372

推薦閱讀更多精彩內容

  • 原文地址 目錄 Java NIO教程 Java NIO 教程(一) 概述 Java NIO 教程(二) Chann...
    步積閱讀 8,923評論 0 11
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,781評論 18 139
  • Java 語言支持的類型分為兩類:基本類型和引用類型。整型(byte 1, short 2, int 4, lon...
    xiaogmail閱讀 1,363評論 0 10
  • ¥開啟¥ 【iAPP實現進入界面執行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 6,482評論 0 17
  • 依窗遠眺,瞭望天涯路;于斯長相守,額頭已爬滿了艱辛;夜凄凄,難覓黎明那一縷曦光,確見那滄桑!夕陽穿透窗欞,...
    阿莢閱讀 231評論 0 16