零、本講學習目標
1、熟悉File類的常用方法
2、掌握File類遍歷目錄文件的使用
3、掌握File類刪除文件及目錄的使用
一、File類概述
通過I/O流可以對文件的內容進行讀寫操作,但對文件本身進行的一些常規操作是無法通過I/O流來實現的,例如創建一個文件、刪除或者重命名某個文件、判斷硬盤上某文件是否存在等。針對文件的這類操作,JDK中提供了一個File類,該類封裝了一個路徑,並提供了一系列的方法用於操作該路徑所指向的文件,本講我們圍繞着File類展開學習。
1、File的類繼承圖
從上圖可以看到,File類是Object類的直接子類,實現了兩個接口:序列化接口(Serializable)和可比較接口(Comparable)。
2、File類的結構
從上圖可以看到,File提供了六種重載的構造方法,還提供了一系列獲取文件屬性的方法。
二、File類常用方法
1、File類常用構造方法
方法聲明 | 功能描述 |
---|---|
File(String pathname) | 通過指定的一個字符串類型的文件路徑來創建一個新的File對象 |
File(String parent, String child) | 根據指定的一個字符串類型的父路徑和一個字符串類型的子路徑(包括文件名稱)創建一個File對象 |
File(File parent, String child) | 根據指定的File類的父路徑和字符串類型的子路徑(包括文件名稱)創建一個File對象 |
2、File類常用普通方法
方法聲明 | 功能描述 |
---|---|
boolean exists() | 判斷File對象對應的文件或目錄是否存在,若存在則返回ture,否則返回false |
boolean delete() | 刪除File對象對應的文件或目錄,若成功刪除則返回true,否則返回false |
boolean createNewFile() | 當File對象對應的文件不存在時,該方法將新建一個此File對象所指定的新文件,若創建成功則返回true,否則返回false |
String getName() | 返回File對象表示的文件或文件夾的名稱 |
String getPath() | 返回File對象對應的路徑 |
String getAbsolutePath() | 返回File對象對應的絕對路徑(在Unix/Linux等系統上,如果路徑是以正斜線/開始,則這個路徑是絕對路徑;在Windows等系統上,如果路徑是從盤符開始,則這個路徑是絕對路徑) |
String getParent() | 返回File對象對應目錄的父目錄(即返回的目錄不包含最後一級子目錄) |
boolean canRead() | 判斷File對象對應的文件或目錄是否可讀,若可讀則返回true,反之返回false |
boolean canWrite() | 判斷File對象對應的文件或目錄是否可寫,若可寫則返回true,反之返回false |
boolean isFile() | 判斷File對象對應的是否是文件(不是目錄),若是文件則返回true,反之返回false |
boolean isFile() | 判斷File對象對應的是否是文件(不是目錄),若是文件則返回true,反之返回false |
boolean isDirectory() | 判斷File對象對應的是否是目錄(不是文件),若是目錄則返回true,反之返回false |
boolean isAbsolute() | 判斷File對象對應的文件或目錄是否是絕對路徑 |
long lastModified() | 返回1970年1月1日0時0分0秒到文件最後修改時間的毫秒值 |
long length() | 返回文件內容的長度 |
String[] list() | 列出指定目錄的全部內容,只是列出名稱 |
String[] list(FilenameFilter filter) | 接收一個FilenameFilter參數,通過該參數可以只列出符合條件的文件 |
File[] listFiles() | 返回一個包含了File對象所有子文件和子目錄的File數組 |
三、利用File類實現文件操作
(一)創建目錄
1、創建方法
調用File對象的mkdir()
方法就可以創建目錄,返回true
,表明創建目錄成功,否則創建失敗。(mk: make;dir: directory)
2、案例演示
- 創建Example2601
package net.hw.lesson26;
import java.io.File;
/**
* 功能:創建目錄
* 作者:華衛
* 日期:2020年05月26日
*/
public class Example2601 {
public static void main(String[] args) {
// 創建File對象,指向一個目錄,僅僅是一個邏輯概念
File dir = new File("d:/park01");
// 調用File對象的創建目錄方法,將邏輯概念轉換成物理實在
boolean isDirMade = dir.mkdir();
// 判斷目錄是否創建成功
if (isDirMade) {
// getPath()方法返回File對象對應的路徑
System.out.println("目錄[" + dir.getPath() + "]創建成功!");
} else {
System.out.println("目錄[" + dir.getPath() + "]創建失敗!");
}
}
}
- 運行程序,查看結果
- 驗證是否在指定位置創建了目錄
- 代碼說明
–File dir = new File("d:/park01");
與File dir = new File("d:\\park01");
是一樣的效果,因爲“\”是轉義字符的打頭字符,所以寫反斜槓目錄分隔符就需要兩個反斜槓“\\”。
– 如果創建File對象的語句變成File dir = new File("park01");
傳入的參數只有目錄名而沒有盤符或路徑,那麼調用dir的mkdir()方法後,將在項目根目錄創建一個park01目錄,同學們不妨驗證一下。 - 再一次運行程序,查看結果
- 說明:失敗的原因是因爲目錄已經存在,我們可以在創建目錄時判斷目錄是否存在,然後給用戶相應的提示。
- 修改Example2601,創建目錄時判斷目錄是否存在,不存在時再調用創建目錄方法
package net.hw.lesson26;
import java.io.File;
/**
* 功能:創建目錄
* 作者:華衛
* 日期:2020年05月26日
*/
public class Example2601 {
public static void main(String[] args) {
// 創建File對象,指向一個目錄,僅僅是一個邏輯概念
File dir = new File("d:/park01");
// 判斷目錄是否存在
if (!dir.exists()) {
// 調用File對象的創建目錄方法,將邏輯概念轉換成物理實在
boolean isDirMade = dir.mkdir();
// 判斷目錄是否創建成功
if (isDirMade) {
// getPath()方法返回File對象對應的路徑
System.out.println("目錄[" + dir.getPath() + "]創建成功!");
} else {
System.out.println("目錄[" + dir.getPath() + "]創建失敗!");
}
} else {
System.out.println("目錄[" + dir.getPath() + "]已經存在!");
}
}
}
- 運行程序,查看結果
- 說明:目錄必須一層一層地創建,比如創建
d:\park01
,然後再創建d:\park01\hw
就沒有問題,否則就會創建失敗。 - 在Windows窗口裏刪除
d:\park01
目錄,程序中直接創建d:\park01\hw
- 先創建
d:\park01
- 再創建
d:\park01\hw
- 結論:利用File對象創建目錄,必須一級目錄一級目錄地創建,就像修建房屋,要一層樓一層樓地往上修,一樓都沒有修,直接修二樓,肯定是要不得的。
(二)創建文件
1、創建方法
調用File對象的creatNewFile()
方法就可以創建文件,返回true
,表明創建文件成功,否則創建失敗,而且有可能拋出無效文件路徑的I/O異常。
2、案例演示
- 創建Example2602
package net.hw.lesson26;
import java.io.File;
import java.io.IOException;
/**
* 功能:創建文件
* 作者:華衛
* 日期:2020年05月26日
*/
public class Example2602 {
public static void main(String[] args) {
// 創建File對象,指向一個文件,僅僅是一個邏輯概念
File file = new File("d:/park01", "love.txt");
try {
// 調用File對象的創建文件方法,將邏輯概念轉換成物理實在
file.createNewFile();
// 提示用戶文件創建成功
System.out.println("文件[" + file.getAbsolutePath() + "]創建成功!");
} catch (IOException e) {
// 提示用戶文件創建失敗
System.out.println("文件[" + file.getAbsolutePath() + "]創建失敗!");
}
}
}
- 代碼說明:創建指向文件的File對象既可以利用構造方法
public File(String parent, String child)
,此時parent
參數是一個路徑字符串,也可以利用構造方法public File(File parent, String child)
,在案例Example2603裏我們會用第二種構造方法來創建文件對象。 - 運行程序,查看結果
- 修改一下創建File對象時傳入的第一個參數,改成一個不存在的目錄,在異常捕獲代碼塊裏添加一條輸出異常信息的語句,然後執行程序,查看效果
- 修改程序,在創建文件時判斷文件是否存在
package net.hw.lesson26;
import java.io.File;
import java.io.IOException;
/**
* 功能:創建文件
* 作者:華衛
* 日期:2020年05月26日
*/
public class Example2602 {
public static void main(String[] args) {
// 創建File對象,指向一個文件,僅僅是一個邏輯概念
File file = new File("d:/park01", "love.txt");
// 判斷文件是否存在
if (!file.exists()) {
try {
// 調用File對象的創建文件方法,將邏輯概念轉換成物理實在
file.createNewFile();
// 提示用戶文件創建成功
System.out.println("文件[" + file.getAbsolutePath() + "]創建成功!");
} catch (IOException e) {
// 提示用戶文件創建失敗
System.out.println("文件[" + file.getAbsolutePath() + "]創建失敗!");
System.err.println("異常信息:" + e.getMessage());
}
} else {
// 提示用戶文件已經存在
System.out.println("文件[" + file.getAbsolutePath() + "]已經存在!");
}
}
}
- 運行程序,查看效果
(三)獲取目錄或文件的屬性
1、獲取方法
2、案例演示
- 創建Example2603
package net.hw.lesson26;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
/**
* 功能:獲取目錄與文件的屬性
* 作者:華衛
* 日期:2020年05月26日
*/
public class Example2603 {
public static void main(String[] args) throws IOException {
// 創建目錄對象(注意目錄是已經存在的)
File dir = new File("d:/park01");
// 創建文件對象(注意文件是已經存在的)
File file = new File(dir, "love.txt");
// 創建簡單日期格式對象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
// 獲取目錄相關屬性
System.out.println("目錄路徑:" + dir.getPath());
System.out.println("目錄父目錄:" + dir.getParent());
System.out.println("目錄絕對路徑:" + dir.getAbsolutePath());
System.out.println("目錄標準路徑:" + dir.getCanonicalPath());
System.out.println("目錄名:" + dir.getName());
System.out.println("目錄長度:" + dir.length());
System.out.println("目錄最後修改時間:" + sdf.format(dir.lastModified()));
System.out.println();
// 獲取文件的相關屬性
System.out.println("文件路徑:" + file.getPath());
System.out.println("文件父目錄:" + file.getParent());
System.out.println("文件絕對路徑:" + file.getAbsolutePath());
System.out.println("文件標準路徑:" + file.getCanonicalPath());
System.out.println("文件名:" + file.getName());
System.out.println("文件長度:" + file.length());
System.out.println("文件最後修改時間:" + sdf.format(file.lastModified()));
}
}
- 運行程序,查看結果
- 修改文件love.txt,添加一點內容
- 再次運行程序,查看結果
(四)遍歷目錄下的文件
1、獲取方法
- 一個是重載的list()返回的是目錄名或文件名數組(可以接收文件名過濾作爲參數)
- 一個是重載的listFiles()返回的是File對象數組(可以接收文件名過濾器或文件過濾器作爲參數)
2、案例演示:顯示指定目錄下所有子目錄與文件的名稱
package net.hw.lesson26;
import java.io.File;
/**
* 功能:顯示指定目錄下所有子目錄與文件的名稱
* 作者:華衛
* 日期:2020年05月26日
*/
public class Example2604 {
public static void main(String[] args) {
// 創建File對象,指向目錄(c:\windows)
File dir = new File("c:/windows");
// 判斷是否是目錄
if (dir.isDirectory()) {
// 獲取指定目錄下全部文件或目錄名
String[] filenames = dir.list();
// 遍歷文件名數組
for (String filename : filenames) {
System.out.println(dir.getPath() + "\\" + filename);
}
} else {
System.err.println("[" + dir.getPath() + "]不是目錄!");
}
}
}
- 運行程序,查看結果
- 除了用增強for循環來遍歷filenames數組,還可以使用JDK8提供的stream的forEach方法來遍歷,當然要利用Lambda表達式
Arrays.stream(filenames).forEach(filename -> System.out.println(dir.getPath() + "\\" + filename));
- 還可以利用Arrays類的asList()方法將數組轉換成數組列表,再利用forEach()和Lambda表達式來遍歷整個數組的全部元素
Arrays.asList(filenames).forEach(filename -> System.out.println(dir.getPath() + "\\" + filename));
- 如果將程序中的目錄名
c:/windows
改成一個文件名c:/windows/win.ini
,運行程序,結果會怎樣呢?我們不妨來試一試。
子目錄名與文件名是混在一起的,那麼怎樣才能將目錄和文件分開顯示呢?
3、案例演示:分開顯示指定目錄下的子目錄與文件
-
方法:要利用File對象的listFiles()方法來獲取指定目錄下的File對象數組,然後利用File對象的isDirectory()方法和isFile()方法來區分獲取的File對象是目錄還是文件。
-
創建Example2605
package net.hw.lesson26;
import java.io.File;
/**
* 功能:分開顯示指定目錄下的子目錄與文件
* 作者:華衛
* 日期:2020年05月26日
*/
public class Example2605 {
public static void main(String[] args) {
// 創建File對象,指向一個目錄(c:\windows)
File dir = new File("c:/windows");
// 獲取指定目錄下的子目錄與文件對象數組
File[] files = dir.listFiles();
// 顯示指定目錄下的子目錄
System.out.println(dir.getPath() + "下的子目錄:");
// 遍歷files數組,篩選出子目錄
for (File file: files) {
if (file.isDirectory()) {
System.out.println(file.getPath());
}
}
System.out.println("=======================");
// 顯示指定目錄下的文件
System.out.println(dir.getPath() + "下的文件:");
// 遍歷files數組,篩選出文件
for (File file: files) {
if (file.isFile()) {
System.out.println(file.getPath());
}
}
}
}
- 運行程序,查看結果
如何查看某個目錄下指定類型的文件?比如我們只想查看c:\windows
目錄下的文本文件。
4、案例演示:顯示指定目錄下某種類型的文件
- 方法:在File對象的list()或listFiles()裏傳入文件名過濾器對象或者利用Lambda表達式來實現文件類型的過濾
- 創建Example2606
package net.hw.lesson26;
import java.io.File;
import java.io.FilenameFilter;
/**
* 功能:顯示指定目錄下某種類型的文件
* 作者:華衛
* 日期:2020年05月26日
*/
public class Example2606 {
public static void main(String[] args) {
// 創建File對象,指向目錄(c:\windows)
File dir = new File("c:/windows");
// 獲取指定目錄下全部可執行文件名
String[] filenames = dir.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".exe");
}
});
System.out.println(dir.getPath() + "下的可執行文件:");
// 遍歷文件名數組
for (String filename: filenames) {
System.out.println(filename);
}
}
}
- 運行程序,查看結果
- 修改程序,採用Lambda表達式來過濾和遍歷
package net.hw.lesson26;
import java.io.File;
import java.util.Arrays;
/**
* 功能:顯示指定目錄下某種類型的文件
* 作者:華衛
* 日期:2020年05月26日
*/
public class Example2606 {
public static void main(String[] args) {
// 創建File對象,指向目錄(c:\windows)
File dir = new File("c:/windows");
// 獲取指定目錄下全部可執行文件名
String[] filenames = dir.list((parent, filename) -> filename.endsWith(".exe"));
System.out.println(dir.getPath() + "下的可執行文件:");
// 文件名數組轉換成數組列表後進行遍歷
Arrays.asList(filenames).forEach(filename -> System.out.println(filename));
}
}
- 運行程序,查看結果
5、案例演示:採用遞歸算法生成指定目錄下某種類型文件的列表
- 注意:目錄下還有目錄,一層又一層的目錄,都要遍歷到,必須採用遞歸才能搞定。
- 創建Example2607
package net.hw.lesson26;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* 功能:生成指定目錄下某種類型文件的列表
* 作者:華衛
* 日期:2020年05月26日
*/
public class Example2607 {
/**
*
* @param dir 目錄
* @param suffix 後綴
* @param typeFileList 類型文件列表
*/
public static void makeTypeFileList(File dir, String suffix, List<String> typeFileList) {
// 獲取指定目錄的File數組
File[] files = dir.listFiles();
// 遍歷File數組
for(int i = 0; i < files.length; i++) {
// 判斷File數組的元素是不是文件
if (files[i].isFile()) {
// 過濾文件類型
if (files[i].getPath().endsWith(suffix)) {
// 將文件添加到文件列表裏
typeFileList.add(files[i].getPath());
}
} else {
// 判斷目錄是否爲空
if (files[i].list() != null) {
// 遞歸調用
makeTypeFileList(files[i], suffix, typeFileList);
}
}
}
}
public static void main(String[] args) {
// 創建目錄對象
File dir = new File("e:/");
// 創建類型文件列表
List<String> typeFileList = new ArrayList<>();
// 調用生成類型文件列表方法
makeTypeFileList(dir, ".mp3", typeFileList);
// 遍歷類型文件列表
typeFileList.forEach(file -> System.out.println(file));
}
}
- 運行程序,查看結果(查看e盤所有mp3文件,比較耗時,要有點耐心)
6、課堂練習:遍歷某個目錄下的全部文件
比如,遍歷“C:\Windows\apppatch”目錄的全部文件:
(五)刪除目錄和文件
1、刪除方法
調用File對象的delete()方法刪除文件或目錄。
2、案例演示:通過遞歸刪除指定目錄下的文件與文件夾
刪除我們在前面創建的d:\park01
,因爲它非空,必須採用遞歸法來刪除它裏面的全部東東。把它刪成空目錄之後,才能最終將它刪除掉。
- 創建Example2608
package net.hw.lesson26;
import java.io.File;
/**
* 功能:通過遞歸刪除指定目錄下的文件與文件夾
* 作者:華衛
* 日期:2020年05月26日
*/
public class Example2608 {
public static void main(String[] args) {
// 創建目錄對象
File dir = new File("d:/park01");
// 調用刪除目錄方法
deleteDir(dir);
// 提示用戶刪除成功
System.out.println("目錄[" + dir.getPath() + "]刪除成功!");
}
/**
* 刪除指定目錄下的全部東東
*
* @param dir
*/
public static void deleteDir(File dir) {
// 獲取指定目錄下的全部File對象
File[] files = dir.listFiles();
// 遍歷File對象數組
for (File file : files) {
// 如果是目錄,則遞歸調用刪除方法
if (file.isDirectory()) {
deleteDir(file);
} else {
file.delete();
}
}
// 刪除指定目錄
dir.delete();
}
}
- 運行程序,查看結果