Java File類(檔案操作類)詳解

2020-07-16 10:05:16
在 Java 中,File 類是 java.io 包中唯一代表磁碟檔案本身的物件,也就是說,如果希望在程式中操作檔案和目錄,則都可以通過 File 類來完成。File 類定義了一些方法來操作檔案,如新建、刪除、重新命名檔案和目錄等。

File 類不能存取檔案內容本身,如果需要存取檔案內容本身,則需要使用輸入/輸出流。

File 類提供了如下三種形式構造方法。
  1. File(String path):如果 path 是實際存在的路徑,則該 File 物件表示的是目錄;如果 path 是檔名,則該 File 物件表示的是檔案。
  2. File(String path, String name):path 是路徑名,name 是檔名。
  3. File(File dir, String name):dir 是路徑物件,name 是檔名。

使用任意一個構造方法都可以建立一個 File 物件,然後呼叫其提供的方法對檔案進行操作。在表 1 中列出了 File 類的常用方法及說明。

表 1  File類的常用方法
方法名稱 說明
boolean canRead() 測試應用程式是否能從指定的檔案中進行讀取
boolean canWrite() 測試應用程式是否能寫當前檔案
boolean delete() 刪除當前物件指定的檔案
boolean exists() 測試當前 File 是否存在
String getAbsolutePath() 返回由該物件表示的檔案的絕對路徑名
String getName() 返回表示當前物件的檔名或路徑名(如果是路徑,則返回最後一級子路徑名)
String getParent() 返回當前 File 物件所對應目錄(最後一級子目錄)的父目錄名
boolean isAbsolute() 測試當前 File 物件表示的檔案是否為一個絕對路徑名。該方法消除了不同平台的差異,可以直接判斷 file 物件是否為絕對路徑。在 UNIX/Linux/BSD 等系統上,如果路徑名開頭是一條斜線/,則表明該 File 物件對應一個絕對路徑;在 Windows 等系統上,如果路徑開頭是碟符,則說明它是一個絕對路徑。
boolean isDirectory() 測試當前 File 物件表示的檔案是否為一個路徑
boolean isFile() 測試當前 File 物件表示的檔案是否為一個“普通”檔案
long lastModified() 返回當前 File 物件表示的檔案最後修改的時間
long length() 返回當前 File 物件表示的檔案長度
String[] list() 返回當前 File 物件指定的路徑檔案列表
String[] list(FilenameFilter) 返回當前 File 物件指定的目錄中滿足指定過濾器的檔案列表
boolean mkdir() 建立一個目錄,它的路徑名由當前 File 物件指定
boolean mkdirs() 建立一個目錄,它的路徑名由當前 File 物件指定
boolean renameTo(File) 將當前 File 物件指定的檔案更名為給定引數 File 指定的路徑名

File 類中有以下兩個常用常數:
  • public static final String pathSeparator:指的是分隔連續多個路徑字串的分隔符,Windows 下指;。例如 java -cp test.jar;abc.jar HelloWorld
  • public static final String separator:用來分隔同一個路徑字串中的目錄的,Windows 下指/。例如 C:/Program Files/Common Files

注意:可以看到 File 類的常數定義的命名規則不符合標準命名規則,常數名沒有全部大寫,這是因為 Java 的發展經過了一段相當長的時間,而命名規範也是逐步形成的,File 類出現較早,所以當時並沒有對命名規範有嚴格的要求,這些都屬於 Java 的歷史遺留問題。

Windows 的路徑分隔符使用反斜線“”,而 Java 程式中的反斜線表示跳脫字元,所以如果需要在 Windows 的路徑下包括反斜線,則應該使用兩條反斜線或直接使用斜線“/”也可以。Java 程式支援將斜線當成平台無關的路徑分隔符。

假設在 Windows 作業系統中有一檔案 D:javaspacehello.java,在 Java 中使用的時候,其路徑的寫法應該為 D:/javaspace/hello.java 或者 D:javaspacehello.java

獲取檔案屬性

在 Java 中獲取檔案屬性資訊的第一步是先建立一個 File 類物件並指向一個已存在的檔案, 然後呼叫表 1 中的方法進行操作。

例 1

假設有一個檔案位於 C:windowsnotepad.exe。編寫 Java 程式獲取並顯示該檔案的長度、是否可寫、最後修改日期以及檔案路徑等屬性資訊。實現程式碼如下:
public class Test02 {
    public static void main(String[] args) {
        String path = "C:/windows/"; // 指定檔案所在的目錄
        File f = new File(path, "notepad.exe"); // 建立File變數,並設定由f變數參照
        System.out.println("C:windowsnotepad.exe檔案資訊如下:");
        System.out.println("============================================");
        System.out.println("檔案長度:" + f.length() + "位元組");
        System.out.println("檔案或者目錄:" + (f.isFile() ? "是檔案" : "不是檔案"));
        System.out.println("檔案或者目錄:" + (f.isDirectory() ? "是目錄" : "不是目錄"));
        System.out.println("是否可讀:" + (f.canRead() ? "可讀取" : "不可讀取"));
        System.out.println("是否可寫:" + (f.canWrite() ? "可寫入" : "不可寫入"));
        System.out.println("是否隱藏:" + (f.isHidden() ? "是隱藏檔案" : "不是隱藏檔案"));
        System.out.println("最後修改日期:" + new Date(f.lastModified()));
        System.out.println("檔名稱:" + f.getName());
        System.out.println("檔案路徑:" + f.getPath());
        System.out.println("絕對路徑:" + f.getAbsolutePath());
    }
}
在上述程式碼中 File 類構造方法的第一個引數指定檔案所在位置,這裡使用C:/作為檔案的實際路徑;第二個引數指定檔名稱。建立的 File 類物件為 f,然後通過 f 呼叫方法獲取相應的屬性,最終執行效果如下所示。
C:windowsnotepad.exe檔案資訊如下:
============================================
檔案長度:193536位元組
檔案或者目錄:是檔案
檔案或者目錄:不是目錄
是否可讀:可讀取
是否可寫:可寫入
是否隱藏:不是隱藏檔案
最後修改日期:Mon Dec 28 02:55:19 CST 2016
檔名稱:notepad.exe
檔案路徑:C:windowsnotepad.exe
絕對路徑:C:windowsnotepad.exe

建立和刪除檔案

File 類不僅可以獲取已知檔案的屬性資訊,還可以在指定路徑建立檔案,以及刪除一個檔案。建立檔案需要呼叫 createNewFile() 方法,刪除檔案需要呼叫 delete() 方法。無論是建立還是刪除檔案通常都先呼叫 exists() 方法判斷檔案是否存在。

例 2

假設要在 C 盤上建立一個 test.txt 檔案,程式啟動時會檢測該檔案是否存在,如果不存在則建立;如果存在則刪除它再建立。

實現程式碼如下:
public class Test03 {
    public static void main(String[] args) throws IOException {
        File f = new File("C:test.txt"); // 建立指向檔案的File物件
        if (f.exists()) // 判斷檔案是否存在
        {
            f.delete(); // 存在則先刪除
        }
        f.createNewFile(); // 再建立
    }
}
執行程式之後可以發現,在 C 盤中已經建立好了 test.txt 檔案。但是如果在不同的作業系統中,路徑的分隔符是不一樣的,例如:
  • Windows 中使用反斜槓表示目錄的分隔符。
  • Linux 中使用正斜槓/表示目錄的分隔符。

那麼既然 Java 程式本身具有可移植性的特點,則在編寫路徑時最好可以根據程式所在的作業系統自動使用符合本地作業系統要求的分隔符,這樣才能達到可移植性的目的。要實現這樣的功能,則就需要使用 File 類中提供的兩個常數。

程式碼修改如下:
public static void main(String[] args) throws IOException {
    String path = "C:" + File.separator + "test.txt"; // 拼湊出可以適應作業系統的路徑
    File f = new File(path);
    if (f.exists()) // 判斷檔案是否存在
    {
        f.delete(); // 存在則先刪除
    }
    f.createNewFile(); // 再建立
}
程式的執行結果和前面程式一樣,但是此時的程式可以在任意的作業系統中使用。

注意:在操作檔案時一定要使用 File.separator 表示分隔符。在程式的開發中,往往會使用 Windows 開發環境,因為在 Windows 作業系統中支援的開發工具較多,使用方便,而在程式發布時往往是直接在 Linux 或其它作業系統上部署,所以這時如果不使用 File.separator,則程式執行就有可能存在問題。關於這一點我們在以後的開發中一定要有所警惕。

建立和刪除目錄

File 類除了對檔案的建立和刪除外,還可以建立和刪除目錄。建立目錄需要呼叫 mkdir() 方法,刪除目錄需要呼叫 delete() 方法。無論是建立還是刪除目錄都可以呼叫 exists() 方法判斷目錄是否存在。

例 3

編寫一個程式判斷 C 盤根目錄下是否存在 config 目錄,如果存在則先刪除再建立。實現程式碼如下:
public class Test04 {
    public static void main(String[] args) {
        String path = "C:/config/"; // 指定目錄位置
        File f = new File(path); // 建立File物件
        if (f.exists()) {
            f.delete();
        }
        f.mkdir(); // 建立目錄
    }
}

遍歷目錄

通過遍歷目錄可以在指定的目錄中查詢檔案,或者顯示所有的檔案列表。File 類的 list() 方法提供了遍歷目錄功能,該方法有如下兩種過載形式。

1. String[] list()

該方法表示返回由 File 物件表示目錄中所有檔案和子目錄名稱組成的字串陣列,如果呼叫的 File 物件不是目錄,則返回 null。

提示:list() 方法返回的陣列中僅包含檔名稱,而不包含路徑。但不保證所得陣列中的相同字串將以特定順序出現,特別是不保證它們按字母順序出現。

2. String[] list(FilenameFilter filter)

該方法的作用與 list() 方法相同,不同的是返回陣列中僅包含符合 filter 過濾器的檔案和目錄,如果 filter 為 null,則接受所有名稱。

例 4

假設要遍歷 C 盤根目錄下的所有檔案和目錄,並顯示檔案或目錄名稱、型別及大小。使用 list() 方法的實現程式碼如下:
public class Test05 {
    public static void main(String[] args) {
        File f = new File("C:/"); // 建立File變數,並設定由f變數變數參照
        System.out.println("檔名稱tt檔案型別tt檔案大小");
        System.out.println("===================================================");
        String fileList[] = f.list(); // 呼叫不帶引數的list()方法
        for (int i = 0; i < fileList.length; i++) { // 遍歷返回的字元陣列
            System.out.print(fileList[i] + "tt");
            System.out.print((new File("C:/", fileList[i])).isFile() ? "檔案" + "tt" : "資料夾" + "tt");
            System.out.println((new File("C:/", fileList[i])).length() + "位元組");
        }
    }
}

由於 list() 方法返回的字元陣列中僅包含檔名稱,因此為了獲取檔案型別和大小,必須先轉換為 File 物件再呼叫其方法。如下所示的是範例的執行效果:
檔名稱  檔案型別  檔案大小
===================================================
$Recycle.Bin  資料夾  4096位元組
Documents and Settings  資料夾  0位元組
Download  資料夾  0位元組
DRIVERS  資料夾  0位元組
FibocomLog  資料夾  0位元組
Gateface  資料夾  0位元組
GFPageCache  資料夾  0位元組
hiberfil.sys  檔案  3375026176位元組
Intel  資料夾  0位元組
KuGou  資料夾  0位元組
logs  資料夾  0位元組
msdia80.dll  檔案  904704位元組
MSOCache  資料夾  0位元組
MyDownloads  資料夾  0位元組
MyDrivers  資料夾  0位元組
news.template  檔案  417位元組
NVIDIA  資料夾  0位元組
OneDriveTemp  資料夾  0位元組
opt  資料夾  0位元組
pagefile.sys  檔案  6442450944位元組
PerfLogs  資料夾  0位元組
Program Files  資料夾  12288位元組
Program Files (x86)  資料夾  8192位元組
ProgramData  資料夾  12288位元組
QMDownload  資料夾  0位元組
Recovery  資料夾  0位元組
swapfile.sys  檔案  268435456位元組
System Volume Information  資料夾  12288位元組
Users  資料夾  4096位元組
Windows  資料夾  16384位元組

例 5

假設希望只列出目錄下的某些檔案,這就需要呼叫帶過濾器引數的 list() 方法。首先需要建立檔案過濾器,該過濾器必須實現 java.io.FilenameFilter 介面,並在 accept() 方法中指定允許的檔案型別。

如下所示為允許 SYS、TXT 和 BAK 格式檔案的過濾器實現程式碼:
public class ImageFilter implements FilenameFilter {
    // 實現 FilenameFilter 介面
    @Override
    public boolean accept(File dir, String name) {
        // 指定允許的檔案型別
        return name.endsWith(".sys") || name.endsWith(".txt") || name.endsWith(".bak");
    }
}
上述程式碼建立的過濾器名稱為 ImageFilter,接下來只需要將該名稱傳遞給 list() 方法即可實現篩選檔案。如下所示為修改後的 list() 方法,其他程式碼與例 4 相同,這裡不再重複。

String fileList[] = f.list(new ImageFilter());


再次執行程式,遍歷結果如下所示:
檔名稱        檔案型別        檔案大小
===================================================
offline_FtnInfo.txt        檔案        296位元組
pagefile.sys        檔案        8436592640位元組