Java - File

By sunwc 2023-03-30 Java

File 類的使用

1.File 類的一個物件,代表一個文件或一個文件目錄(俗稱:文件夾)

2.File 類宣告在 java.io package下

3.File 類涉及到關於文件或文件目錄的創建、刪除、重命名、修改時間、取得文件大小等方法,並未涉及到寫入或讀取文件內容的操作。如果需要讀取或寫入文件內容,必須使用IO流來完成

4.File 類的物件常會作為參數傳遞到流的 constructor 中,指名讀取或寫入的 “終點”

File 常用方法

  • public String getAbsolutePath():取得絕對路徑
  • public String getPath():取得路徑
  • public String getName():取得名稱
  • public String getParent():取得上層文件目錄路徑;若無,回傳null
  • public long length():取得文件長度(即byte數);不能取得目錄的l長度
  • public long lastModified():取得最後一次的修改時間,毫秒值
/**
    * 測試當文件都不存在的時候
    */
@Test
public void fileTest() {

    File file1 = new File("hello.txt");
    File file2 = new File("d:\\io\\hi.txt");

    System.out.println(file1.getAbsolutePath());
    System.out.println(file1.getPath());
    System.out.println(file1.getName());
    System.out.println(file1.getParent());
    System.out.println(file1.length());
    System.out.println(new Date(file1.lastModified()));

    System.out.println();

    System.out.println(file2.getAbsolutePath());
    System.out.println(file2.getPath());
    System.out.println(file2.getName());
    System.out.println(file2.getParent());
    System.out.println(file2.length());
    System.out.println(file2.lastModified());
}

輸出結果:

C:\Users\ching\IdeaProjects\JavaSenior\day08\hello.txt
hello.txt
hello.txt
null
11
Thu Mar 30 10:21:01 GMT+08:00 2023

d:\io\hi.txt
d:\io\hi.txt
hi.txt
d:\io
0
0
  • public String[] list():取得指定目錄下的所有文件或者文件目錄的名稱陣列
  • public File[] listFiles():取得指定目錄下的所有文件或文件目錄的File陣列
@Test
    public void listFileTest() {
        File file = new File("C:\\Users\\ching\\IdeaProjects\\JavaSenior");

        String[] list = file.list();

        for(String name: list) {
            System.out.println(name);
        }

        System.out.println();

        File[] files = file.listFiles();

        for (File file1 : files) {
            System.out.println(file1);
        }
    }

輸出結果:

.idea
day01
day02
day03
day04
day05
day06
day07
day08
JavaSenior.iml
out

C:\Users\ching\IdeaProjects\JavaSenior\.idea
C:\Users\ching\IdeaProjects\JavaSenior\day01
C:\Users\ching\IdeaProjects\JavaSenior\day02
C:\Users\ching\IdeaProjects\JavaSenior\day03
C:\Users\ching\IdeaProjects\JavaSenior\day04
C:\Users\ching\IdeaProjects\JavaSenior\day05
C:\Users\ching\IdeaProjects\JavaSenior\day06
C:\Users\ching\IdeaProjects\JavaSenior\day07
C:\Users\ching\IdeaProjects\JavaSenior\day08
C:\Users\ching\IdeaProjects\JavaSenior\JavaSenior.iml
C:\Users\ching\IdeaProjects\JavaSenior\out
  • public boolean renameTo(File dest):把文件重命名為指定的文件路徑,例如file1.renameTo(file2)

若想要保證回傳 true, file1 需在硬碟中、且 file2 目錄在硬碟中但檔案不在硬碟中

@Test
public void renameToTest() {

    File file1 = new File("C:\\Users\\ching\\IdeaProjects\\JavaSenior\\day08\\hello.txt");
    File file2 = new File("C:\\io\\hi.txt");

    if (!file2.exists()) {
        new File(file2.getParent()).mkdir();
    }

    System.out.println(file1.renameTo(file2));
}
  • public boolean isDirectory():判斷是否是文件目錄
  • public boolean isFile():判斷是否是文件
  • public boolean exists():判斷是否存在
  • public boolean canRead():判斷是否可讀
  • public boolean canWrite():判斷是否可寫
  • public boolean isHidden():判斷是否隱藏
@Test
public void fileBooleanTest() {

    // 存在的檔案
    File file1 = new File("C:\\Users\\ching\\IdeaProjects\\JavaSenior\\hello.txt");
    // 不存在的檔案
    file1 = new File("C:\\Users\\ching\\IdeaProjects\\JavaSenior\\hello1.txt");
    System.out.println(file1.exists());
    System.out.println(file1.isFile());
    System.out.println(file1.isDirectory());
    System.out.println(file1.canWrite());
    System.out.println(file1.canRead());
    System.out.println(file1.isHidden());

    System.out.println();

    // 存在的目錄
    File file2 = new File("C:\\io");
    // 不存在的目錄
    file2 = new File("C:\\io1");
    System.out.println(file2.exists());
    System.out.println(file2.isFile());
    System.out.println(file2.isDirectory());
    System.out.println(file2.canWrite());
    System.out.println(file2.canRead());
    System.out.println(file2.isHidden());
}

創建硬碟對應的文件或文件目錄

  • public boolean createNewFile():創建文件;若文件存在,則不創建,回傳false

  • public boolean mkdir():創建文件目錄;若此文件目錄存在,就不創建了;若此文件目錄的上層目錄不存在,也不創建

  • public boolean mkdirs():創建文件目錄;若上層目錄不存在,一並創建

  • public boolean delete():刪除文件或者文件夾;注意Java中的刪除不走回收站

@Test
public void fileCreationTest() throws IOException {

    // 不存在的檔案
    File file1 = new File("hello1.txt");

    if (!file1.exists()) {
        file1.createNewFile();
        System.out.println("創建成功");
    } else {
        file1.delete();
        System.out.println("刪除成功");
    }
}

練習

  • 判斷指定目錄下是否有後綴名為.jpg的文件,如果有,就輸出該文件名稱
@Test
public void getPostfixJPG() {

    File file = new File("C:\\Users\\ching\\Pictures");
    File[] files = file.listFiles();

    for (File file1 : files) {
        String fileName = file1.getName();
        if (fileName.endsWith(".jpg")) {
            System.out.println(fileName);
        }
    }
}
  • 創建一個與 file 同目錄下的另一個文件,文件名為:helloworld.txt
@Test
public void createNewFileTest() throws IOException {

    File file = new File("C:\\Users\\ching\\IdeaProjects\\JavaSenior\\day08\\hello.txt");
    File destFile = new File(file.getParent(), "helloworld.txt");

    if (!destFile.exists()) {
        destFile.createNewFile();
        System.out.println("創建成功");
    }
}
  • 遍歷指定目錄所有文件名稱,包括子文件目錄中的文件
    • 拓展1:並計算指定目錄下所有檔案佔用空間的大小
 @Test
    public void loopAllUnderTheDirectory() {

        File file = new File("C:\\IdeaProjects\\ infotrends-plugin-cathay");
        long totalOccupied = printFilePath(file);
        System.out.println(totalOccupied);

    }


    /**
     * 這道題涉及到了遞迴,對遞迴的感悟是:
     * <p>
     * 每執行一次遞迴方法就開闢一塊不同的Stack空間,所以遞迴方法裡變數儘管同名,但值不同。
     * 遞迴如果按層次理解,遞迴先往內一層一層進入,在最內層方法執行結束後,外層的方法沒有結束(return),會再往外一層層return。最重要的是取得每層方法的回傳值結果。
     *
     * @param dir
     * @return
     */
    private long printFilePath(File dir) {
        long totalOccupied = 0L;
       
        if (dir.isFile()) {
            // 是檔案就直接做事
            System.out.println(dir.getAbsolutePath());
            // 是檔案就計算檔案bytes數
            totalOccupied += dir.length();
        } else {
            // 是目錄就展開目錄後再調用自己 再判斷子層裡是目錄還是檔案
            
            File[] listFiles = dir.listFiles();
            for (File listFile : listFiles) {
                // 收集每層遞迴方法回傳的值,而不要把需要收集的值傳遞過去
                totalOccupied += printFilePath(listFile);
            }
        }

        return totalOccupied;
    }

參考來源


  • 拓展2:刪除指定文件目錄及其下的所有文件

      @Test
    public void deleteFileTest() {
    
        File file = new File("C:\\IdeaProjects\\infotrends-plugin-cathay");
        deleteFile(file);
    }
    
    private boolean deleteFile(File dir) {
    
    
        if (dir.isFile()) {
            // 是檔案就直接做事
            dir.delete();
        } else {
            // 是目錄就展開目錄後再調用自己 再判斷子層裡是目錄還是檔案
            File[] listFiles = dir.listFiles();
            for (File listFile : listFiles) {
                deleteFile(listFile);
            }
        }
        // 指定目錄此時為空,可以刪除
        return dir.delete();
    }
    

    參考來源