暑期自學 Day 02 | File 類 和 IO 流(二)

Borris發表於2020-05-06

遞迴

這一節開頭提到了遞迴,應該是後面有用,先複習一下。

  • 兩種:直接遞迴(自己呼叫自己),間接遞迴(A呼叫B,B呼叫C…)。
  • 要有終止條件,否則無限呼叫導致棧記憶體溢位
  • 構造方法不可遞迴

*在遍歷檔案時使用到了:只要是資料夾,就遞迴呼叫自定義遍歷方法遍歷下級資料夾

FileFilter 過濾器的原理和使用

FileFilter
  • 介面,用於抽象路徑名(File 物件)的過濾器。
  • 內含抽象方法
    • boolean accept(File pathname) 測試指定抽象路徑是否包含在某個路徑列表中
      • File pathName - 使用listFiles()方法遍歷目錄得到的File類物件
      • 如果返回 true,則繼續遍歷;如果返回 false,則停止遍歷該 File 類物件
FilenameFilter
  • 介面,用於過濾檔名稱

  • 內含抽象方法

    • boolean accept(File dir, String name) 測試指定檔案是否包含在某一檔案列表,注意:第一個引數型別是 File 型別,第二個引數是 String 型別。
  • 兩個介面的抽象方法都需要自己寫實現類,重寫過濾方法 accept(),自定義過濾規則。

  • 兩個介面的區別:???

過濾器原理
  • 需求: 過濾指定型別的檔案,如以.java結尾的檔案
  • 明確
    • accept() 方法由誰呼叫?- listFiles()
    • accept() 方法引數 pathname 是什麼?- 由 listFiles() 遍歷得到的所有 File 類檔案/檔名物件
      • listFiles() 做了哪三件事?看以下程式碼:
          File dir = new File("D:\\TAMU");
          File[] files = dir.listFiles(new FileFilter()); // 傳遞過濾器物件給 listFiles() 方法
        1. listFiles() 遍歷了 dir 目錄下的每一個資料夾和檔案,並將它們封裝成 File 類物件。
        2. listFiles() 呼叫了 FileFilter() 中的 accept() 方法
        3. listFIles() 將封裝好的 File 類物件陣列傳遞給 accept 方法的引數 filename。
    • 由於兩個過濾器藉口均只有一個抽象方法,我們可以在給 listFiles() 傳參時使用 Lamda 表示式實現介面,而不用額外寫一個實現類。

IO流 (輸入輸出流)

  • 流:資料(字元,位元組)。1 字元 = 2位元組;1位元組 = 8 二進位制位。
  • 位元組流:InputStream, OutputStream;字元流:Reader, Writer
  • 為什麼要在使用完 IO 流後釋放資源?由於 Java 的垃圾回收機制無法對系統資源進行釋放,所以需要手動釋放,避免資源浪費。
位元組輸出流(OutputStream)
  • OutputStream 是抽象類,把記憶體中的資料寫入磁碟的檔案中
  • 資料寫入原理:java 程式 -> JVM -> OS -> OS 呼叫寫資料的方法 -> 把資料寫入檔案
    • 一些共性成員方法
      • public void close() 關閉輸出流並釋放相關資源
      • public void flush() 重新整理輸出流並寫出緩衝的輸出位元組
      • public void write(byte[] b) 將b.length位元組從位元組陣列寫入輸出流
      • public void write(byte[] b, int off, int len) 將從b[off]開始,len個位元組的資料從陣列輸出到輸出流
    • 使用步驟
      1. 建立一個 FileOutputStream 物件,構造方法中寫入資料到目的地
      2. 呼叫 FileOutputStream 物件中的 write 方法,把資料寫入到檔案中
      3. 釋放資源
        • 注意:三個步驟均需要處理 IOException; 在實際操作中構造 FileOutputStream 物件時,只有傳入絕對檔案路徑才能寫入成功,傳入相對路徑只能建立空檔案。不知道這是為什麼?
    • 往檔案後追加寫資料
      • FileOutputStream(String name, boolean append)FileOutputStream(File file, boolean append) append 為 true 時,可以在原檔案中續寫。
    • 寫入換行
      • fos.write("\r\n".getBytes())
位元組輸入流 (InputStream)
  • InputStream 是抽象類,把磁碟檔案的資料讀取到記憶體中
  • java 程式 -> JVM -> OS -> OS 呼叫讀取資料的方法 -> 把資料讀取出
    • 一些共性成員方法
      • public void close() 關閉輸入流並釋放相關資源
      • public int read() 從輸入流中讀取下一個位元組
      • public int read(byte[] b) 從輸入流中讀取一定數量的位元組
    • 使用步驟
      1. 建立一個 FileInputStream 物件,構造方法中傳遞資料讀取的目的地
      2. 呼叫 FileInputStream 物件中的 read 方法,將指定檔案中的位元組讀出
      3. 釋放資源
    • 連續讀取檔案中位元組時會使用到迴圈,程式碼示例如下
      FileInputStream fis = new FileInputStream("d:\\test\\a.txt");
      int len = 0; // 用於獲取返回位元組的整型變數
      while ((len = fis.read()) != -1) { // 讀取返回值為 -1 時說明檔案資料全部讀完
        System.out.println((char)len);
      }
      fis.close(); // **釋放資源很重要**
    • 一次讀取多個位元組的方法
      int read(byte[] b) 從輸入流中讀取一定數量的位元組,並儲存在緩衝區陣列 b 中(一般定義為 1024 的倍數)
      • 也還是明確兩件事情:
        • byte[] 陣列的作用?byte陣列,有緩衝作用。每讀取多個位元組覆蓋相應陣列空間,如果最後剩餘位元組數 n 少於陣列長度,只覆蓋前 n 個陣列空間
        • 返回值 int 是什麼?是所讀取位元組的數量。如果讀完返回 -1
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章