1. 程式人生 > 實用技巧 >Java IO流基礎

Java IO流基礎

什麼是IO流

Java中的IO

  瞭解什麼是IO流之前,要先知道什麼是IO。IO,就是in和out(即輸入和輸出),指應用程式和外部裝置之間的資料傳遞,常見的外部裝置包括檔案、管道、網路連線等。

流的概念與特性

概念

  Java 中是通過流處理IO 的。流(Stream),是一個抽象的概念,是指一連串的資料(字元或位元組),是以先進先出的方式傳送資訊的通道。當程式需要讀取資料時,就會開啟一個通向資料來源的流,同理,當程式需要寫入資料時,就會開啟一個通向目的地的流。

特性

關於流的特性有以下幾點:

  1. 先進先出:最先寫入輸出流的資料最先被輸入流讀取到。
  2. 順序存取:可以一個接一個地往流中寫入一串位元組,讀出時也將按寫入順序讀取一串位元組,不能隨機訪問中間的資料。(RandomAccessFile
    除外,它可以對檔案隨機訪問的操作,訪問包括讀和寫操作)
  3. 只讀或只寫:每個流只能是輸入流或輸出流的一種,不能同時具備兩個功能,輸入流只能進行讀操作,對輸出流只能進行寫操作。在一個數據傳輸通道中,如果既要寫入資料,又要讀取資料,則要分別提供兩個流。

IO流的分類

IO分類圖如下(詳細內容可檢視API文件):

IO流主要的分類方式有以下3種:

  1. 按資料流的方向:輸入流、輸出流
  2. 按處理資料單位:位元組流、字元流
  3. 按功能:節點流、處理流

輸入流與輸出流

  這裡要注意的是:輸入與輸出是相對於應用程式而言的,比如檔案讀寫,讀取檔案是輸入流,寫檔案是輸出流(即流向記憶體是輸入流,流出記憶體的輸出流),不要搞反,不是很清楚可以看下圖。

位元組流與字元流

  Unicode 編碼中,一個英文為1個位元組,一箇中文為2個位元組。而在UTF-8編碼中,一箇中文字元是3個位元組。如果使用位元組流處理中文,如果一次讀寫一個字元對應的位元組數就不會有問題,一旦將一個字元對應的位元組分裂開來,就會出現亂碼了。為了更方便地處理中文這些字元,Java就推出了字元流。

  位元組流和字元流的用法幾乎完全一樣,區別在於位元組流和字元流所操作的資料單元不同,位元組流操作的單元是資料單元是8位的位元組(即1個位元組),字元流操作的是資料單元為16位的字元(即1個字元或2個位元組)。

位元組流和字元流的其他區別:

  1. 位元組流一般用來處理影象、視訊、音訊、PPT、Word等型別的檔案。字元流一般用於處理純文字型別的檔案,如TXT檔案等,但不能處理影象視訊等非文字檔案。簡單說就是就是:位元組流可以處理一切檔案,而字元流只能處理純文字檔案。
  2. 位元組流本身沒有緩衝區,緩衝位元組流相對於位元組流,效率提升非常高。而字元流本身就帶有緩衝區,緩衝字元流相對於字元流效率提升就不是那麼大了。

節點流和處理流

  1. 節點流:直接操作資料讀寫的流類,比如FileInputStream
  2. 處理流:對一個已存在的流的連結和封裝,通過對資料進行處理為程式提供功能強大、靈活的讀寫功能,例如BufferedInputStream(緩衝位元組流)

  處理流和節點流應用了Java的裝飾者設計模式。下圖就很形象地描繪了節點流和處理流,處理流是對節點流的封裝,最終的資料處理還是由節點流完成的。

緩衝流:

  在諸多處理流中,有一個非常重要,那就是緩衝流。程式與磁碟的互動相對於記憶體運算是很慢的,容易成為程式的效能瓶頸。減少程式與磁碟的互動,是提升程式效率一種有效手段。緩衝流,就應用這種思路:普通流每次讀寫一個位元組,而緩衝流在記憶體中設定一個快取區,緩衝區先儲存足夠的待操作資料後,再與記憶體或磁碟進行互動。這樣,在總資料量不變的情況下,通過提高每次互動的資料量,減少了互動次數。需要注意的是,緩衝流效率不一定高,在某些情形下,緩衝流效率反而更低,具體請見IO流效率對比。


位元組流

一切皆為位元組

  一切檔案資料(文字、圖片、視訊等)在儲存時,都是以二進位制數字的形式儲存,都一個一個的位元組,同理傳輸時一樣如此,所以位元組流可以傳輸任意檔案資料。在操作流的時候要時刻明確,無論使用什麼樣的流物件,底層傳輸的始終為二進位制資料。

位元組輸出流【OutputStream】

  java.io.OutputStream 抽象類是表示位元組輸出流的所有類的超類,將指定的位元組資訊寫出到目的地。它定義了位元組輸出流的基本共性功能方法如下:
  • public void close() :關閉此輸出流並釋放與此流相關聯的任何系統資源。
  • public void flush() :重新整理此輸出流並強制任何緩衝的輸出位元組被寫出。
  • public void write(byte[] b) :將 b.length位元組從指定的位元組陣列寫入此輸出流。
  • public void write(byte[] b, int off, int len) :從指定的位元組陣列寫入 len(長度)位元組,從偏移量 off(索引)開始輸出到此輸出流。
  • public abstract void write(int b) :將指定的位元組輸出流。

小貼士:

  1. close()方法,當完成流的操作時,必須呼叫此方法,釋放系統資源。
  2. 在建立位元組輸出流物件和使用write()方法寫出資料時,會分別丟擲FileNotFoundException 和IOException異常,要注意的是,IOException異常是FileNotFoundException異常的父類,所以這裡我們直接丟擲IOException異常就可以了。

FileOutputStream類

  OutputStream 有很多子類,我們從最常見的一個類FileOutputStream類開始。java.io.FileOutputStream 類是檔案輸出流,用於將資料寫出到檔案。

構造方法

  • public FileOutputStream(File file) :建立一個向指定File物件表示的檔案中寫入資料的檔案輸出流。
  • public FileOutputStream(String name) : 建立一個向具有指定名稱的檔案中寫入資料的輸出檔案流。

  引數 File file:目的地是一個檔案  String name:目的地是一個檔案的路徑

 注意:當你建立一個流物件時,必須傳入一個檔案路徑。該路徑下,如果沒有這個檔案,會建立該檔案。如果有這個檔案,會清空這個檔案的資料。

作用:

  1. 建立一個Fileoutputstream物件
  2. 會根據構造方法中傳遞的檔案/檔案路徑,建立一個空的檔案
  3. 會把FiLeOutputStream物件指向建立好的檔案

構造方法程式碼演示:

public class FileOutputStreamConstructor throws IOException { 
    public static void main(String[] args) { 
        // 使用File物件建立流物件 
        File file = new File("a.txt"); 
        FileOutputStream fos = new FileOutputStream(file);
        // 使用檔名稱建立流物件 
        FileOutputStream fos = new FileOutputStream("b.txt"); 
    } 
}

寫出位元組資料:

原理:(記憶體-->硬碟)

  java程式-->JVM(java虛擬機器 )-->OS(作業系統)-->OS呼叫寫資料的方法-->把資料寫入到檔案中

方法:

  • 寫出位元組: write(int b) 方法,每次可以寫出一個位元組資料,程式碼演示:
public class FOSWrite {
    public static void main(String[] args) throws IOException { 
        // 使用檔名稱建立流物件 
        FileOutputStream fos = new FileOutputStream("fos.txt"); 
        // 寫出資料
        fos.write(97);//寫出第1個位元組 
        fos.write(98);//寫出第2個位元組 
        fos.write(99);//寫出第3個位元組 
        // 關閉資源 
        fos.close(); 
    } 
} 
輸出結果:
abc
  • 寫出位元組陣列: write(byte[] b) ,每次可以寫出陣列中的資料,程式碼演示:
public class FOSWrite { 
    public static void main(String[] args) throws IOException { 
        // 使用檔名稱建立流物件 
        FileOutputStream fos = new FileOutputStream("fos.txt"); 
        // 字串轉換為位元組陣列 
        byte[] b = "張三李四王五".getBytes(); 
        // 寫出位元組陣列資料 
        fos.write(b); 
        // 關閉資源 
        fos.close(); 
    } 
}
輸出結果: 
張三李四王五
  • 寫出指定長度位元組陣列: write(byte[] b, int off, int len) ,每次寫出從off索引開始,len個位元組,程式碼演示:
public class FOSWrite { 
    public static void main(String[] args) throws IOException { 
        // 使用檔名稱建立流物件 
        FileOutputStream fos = new FileOutputStream("fos.txt"); 
        // 字串轉換為位元組陣列 
        byte[] b = "abcde".getBytes(); 
        // 寫出從索引1開始,2個位元組。索引1是b,兩個位元組,也就是bc。 
        fos.write(b,1,2); 
        // 關閉資源 
        fos.close();
    } 
}
輸出結果: 
bc

資料追加續寫

  每次程式執行,建立輸出流物件,都會清空目標檔案中的資料。那麼如果要保留目標檔案中資料,繼續新增新資料,就要使用如下方法:
  • public FileOutputStream(File file, boolean append) : 建立檔案輸出流以寫入由指定的 File物件表示的檔案。
  • public FileOutputStream(String name, boolean append) : 建立檔案輸出流以指定的名稱寫入檔案。
  這兩個構造方法,引數中都需要傳入一個boolean型別的值, true 表示追加資料, false 表示清空原有資料。

程式碼使用演示:

public class FOSWrite { 
    public static void main(String[] args) throws IOException { 
        // 使用檔名稱建立流物件並設定資料追加續寫
        FileOutputStream fos = new FileOutputStream("fos.txt",true); 
        // 字串轉換為位元組陣列 
        byte[] b = "abcde".getBytes(); 
        // 寫出位元組陣列資料 
        fos.write(b); 
        // 關閉資源 
        fos.close(); 
    } 
}
檔案操作前:
bc 
檔案操作後:
bcabcde    

寫出換行

  Windows系統裡,換行符號是 \r\n 。回車符 \r 和換行符 \n : 回車符:回到一行的開頭(return) 換行符:下一行(newline)。   系統中的換行:
  • Windows系統裡,每行結尾是 回車+換行 ,即 \r\n ;
  • Unix系統裡,每行結尾只有 換行 ,即 \n ;
  • Mac系統裡,每行結尾是 回車 ,即 \r 。

程式碼使用演示:

public class FOSWrite { 
    public static void main(String[] args) throws IOException { 
        // 使用檔名稱建立流物件 
        FileOutputStream fos = new FileOutputStream("fos.txt"); 
        // 定義位元組陣列 
        byte[] words = {97,98,99,100,101}; 
        // 遍歷陣列 
        for (int i = 0; i < words.length; i++) { 
            // 寫出一個位元組 
            fos.write(words[i]); 
            // 寫出一個換行, 換行符號轉成陣列寫出 
            fos.write("\r\n".getBytes()); 
        }
         // 關閉資源 
         fos.close(); 
    } 
}
輸出結果:
a
b
c
d
e    

位元組輸入流【InputStream】

  java.io.InputStream 抽象類是表示位元組輸入流的所有類的超類,可以讀取位元組資訊到記憶體中。它定義了位元組輸入流的基本共性功能方法。
  • public void close() :關閉此輸入流並釋放與此流相關聯的任何系統資源。
  • public abstract int read() : 從輸入流讀取資料的下一個位元組。
  • public int read(byte[] b) : 從輸入流中讀取一些位元組數,並將它們儲存到位元組陣列 b中 。

小貼士:

  1. close方法,當完成流的操作時,必須呼叫此方法,釋放系統資源。
  2. 在建立位元組輸入流物件和使用read()方法讀取資料時,會分別丟擲FileNotFoundException 和IOException異常,要注意的是,IOException異常是FileNotFoundException異常的父類,所以這裡我們直接丟擲IOException異常就可以了。

FileInputStream類

  java.io.FileInputStream 類是檔案輸入流,從檔案中讀取位元組。

構造方法

  • FileInputStream(File file) : 通過開啟與實際檔案的連線來建立一個 FileInputStream ,該檔案由檔案系統中的 File物件 fifile命名。
  • FileInputStream(String name) : 通過開啟與實際檔案的連線來建立一個 FileInputStream ,該檔案由檔案系統中的路徑名 name命名。

  引數:讀取檔案的資料來源 File file:檔案   String name:檔案的路徑

  注意:當你建立一個流物件時,必須傳入一個檔案路徑。該路徑下,如果沒有該檔案,會丟擲 FileNotFoundException 。

構造方法程式碼演示:

public class FileInputStreamConstructor throws IOException{ 
    public static void main(String[] args) { 
        // 使用File物件建立流物件 
        File file = new File("a.txt"); 
        FileInputStream fis = new FileInputStream(file); 
        // 使用檔名稱建立流物件 
        FileInputStream fis = new FileInputStream("b.txt"); 
    } 
}

作用:

  1. 會建立一個FileInputStream物件
  2. 會把FileInputstream物件指向構造方法中要讀取的檔案

讀取位元組資料

原理:(硬碟-->記憶體)

  java程式-->JVM(java虛擬機器 )-->OS(作業系統)-->OS呼叫讀取資料的方法-->從檔案中讀取資料

方法:

  • 讀取位元組: read():每次可以讀取一個位元組的資料,返回值int型別,讀取到檔案末尾,返回 -1 ,程式碼演示:
public class FISRead { 
    public static void main(String[] args) throws IOException{ 
        // 使用檔名稱建立流物件,檔案內容為abcde
        FileInputStream fis = new FileInputStream("read.txt"); 
        // 讀取資料,返回一個位元組 
        int read = fis.read(); 
        System.out.println((char) read); 
        read = fis.read(); 
        System.out.println((char) read); 
        read = fis.read();
        System.out.println((char) read); 
        read = fis.read(); 
        System.out.println((char) read); 
        read = fis.read(); 
        System.out.println((char) read); 
        // 讀取到末尾,返回‐1 
        read = fis.read(); 
        System.out.println( read); 
        // 關閉資源 
        fis.close(); 
    } 
}
輸出結果: 
a
b
c
d
e
‐1

  迴圈改進讀取方式,程式碼演示:

public class FISRead { 
    public static void main(String[] args) throws IOException{ 
        // 使用檔名稱建立流物件,檔案內容為abcde
        FileInputStream fis = new FileInputStream("read.txt");
        // 定義變數,儲存資料 
        int b ; 
        // 迴圈讀取 
        while ((b = fis.read())!=‐1) { 
            System.out.println((char)b); 
        }
        // 關閉資源 
        fis.close(); 
    }
}
輸出結果: 
a
b
c
d
e

小貼士:

  1. 雖然讀取了一個位元組,但是會自動提升為int型別。
  2. 流操作完畢後,必須釋放系統資源,呼叫close方法,千萬記得。
  • 使用位元組陣列讀取: read(byte[] b) ,每次讀取b的長度個位元組到陣列中,返回讀取到的有效位元組個數,讀取到末尾時,返回 -1 ,程式碼演示:
public class FISRead { 
    public static void main(String[] args) throws IOException{ 
        // 使用檔名稱建立流物件,檔案內容為abcde
        FileInputStream fis = new FileInputStream("read.txt");// 定義變數,作為有效個數 
        int len ; 
        // 定義位元組陣列,作為裝位元組資料的容器 
        byte[] b = new byte[2]; 
        // 迴圈讀取 
        while (( len= fis.read(b))!=‐1) { 
            // 每次讀取後,把陣列變成字串列印 
            System.out.println(new String(b)); 
        }
        // 關閉資源 
        fis.close(); 
    } 
}
輸出結果: 
ab
cd
ed
  錯誤資料 d ,是由於最後一次讀取時,只讀取一個位元組 e ,陣列中,上次讀取的資料沒有被完全替換,所以要通過 len ,獲取有效的位元組,程式碼演示:
public class FISRead { 
    public static void main(String[] args) throws IOException{ 
        // 使用檔名稱建立流物件,檔案內容為abcde
        FileInputStream fis = new FileInputStream("read.txt"); 
        // 定義變數,作為有效個數 
        int len ; 
        // 定義位元組陣列,作為裝位元組資料的容器 
        byte[] b = new byte[2]; 
        // 迴圈讀取 
        while (( len= fis.read(b))!=‐1) { 
            // 每次讀取後,把陣列的有效位元組部分,變成字串列印 
            System.out.println(new String(b,0,len));// len 每次讀取的有效位元組個數 
        }
        // 關閉資源 
        fis.close(); 
    } 
}
輸出結果: 
ab
cd
e

小貼士:

  使用陣列讀取,每次讀取多個位元組,減少了系統間的IO操作次數,從而提高了讀寫的效率,建議開發中使用。

使用位元組陣列讀取資料明確兩件事情:

  1. 方法的引數byte[]的作用?
    起到緩衝作用,儲存每次讀取到的多個位元組
    陣列的長度一般定義為1024(1kb)或者1024的整數倍
  2. 方法的返回值int是什麼?
    每次讀取的有效位元組個數

位元組流案例

  說明:圖片複製,從已有的檔案中讀取位元組,將該位元組寫出到另一個檔案中

案例實現:

public class Copy { 
    public static void main(String[] args) throws IOException { 
        // 1.建立流物件 
        // 1.1 指定資料來源 
        FileInputStream fis = new FileInputStream("D:\\test.jpg"); 
        // 1.2 指定目的地 
        FileOutputStream fos = new FileOutputStream("test_copy.jpg");
        // 2.讀寫資料 
        // 2.1 定義陣列 
        byte[] b = new byte[1024];
        // 2.2 定義長度 
        int len; 
        // 2.3 迴圈讀取 
        while ((len = fis.read(b))!=‐1) { 
            // 2.4 寫出資料 
            fos.write(b, 0 , len); 
        }
        // 3.關閉資源 
        fos.close(); 
        fis.close(); 
    } 
}

小貼士:

  • 流的關閉原則:先開後關,後開先關。


字元流

  當使用位元組流讀取文字檔案時,可能會有一個小問題。就是遇到中文字元時,可能不會顯示完整的字元,那是因為一箇中文字元可能佔用多個位元組儲存。所以Java提供一些字元流類,以字元為單位讀寫資料,專門用於處理文字檔案。

字元輸出流【Writer】

  java.io.Writer 抽象類是表示用於寫出字元流的所有類的超類,將指定的字元資訊寫出到目的地。它定義了位元組輸出流的基本共性功能方法。
  • void write(int c) 寫入單個字元。
  • void write(char[] cbuf) 寫入字元陣列。
  • abstract void write(char[] cbuf, int off, int len) 寫入字元陣列的某一部分,offff陣列的開始索引,len寫的字元個數。
  • void write(String str) 寫入字串。
  • void write(String str, int off, int len) 寫入字串的某一部分,offff字串的開始索引,len寫的字元個數。
  • void flush() 重新整理該流的緩衝。
  • void close() 關閉此流,但要先重新整理它。

FileWriter類

  java.io.FileWriter 類是寫出字元到檔案的便利類。構造時使用系統預設的字元編碼和預設位元組緩衝區。

構造方法

  • FileWriter(File file) : 建立一個新的 FileWriter,給定要寫入資料的File物件。
  • FileWriter(String fileName) : 建立一個新的 FileWriter,給定要寫入資料的檔案的名稱。
  當你建立一個流物件時,必須傳入一個檔案路徑,類似於FileOutputStream。

構造舉例,程式碼如下:

public class FileWriterConstructor { 
    public static void main(String[] args) throws IOException { 
        // 使用File物件建立流物件 
        File file = new File("a.txt"); 
        FileWriter fw = new FileWriter(file); 
        // 使用檔名稱建立流物件 
        FileWriter fw = new FileWriter("b.txt"); 
    } 
}

寫出字元資料

  • 寫出字元: write(int b) 方法,每次可以寫出一個字元資料,程式碼使用演示:
public class FWWrite { 
    public static void main(String[] args) throws IOException { 
        // 使用檔名稱建立流物件 
        FileWriter fw = new FileWriter("fw.txt");
        // 寫出資料 
        fw.write(97); // 寫出第1個字元 
        fw.write('b'); // 寫出第2個字元 
        fw.write('c'); // 寫出第3個字元 
        fw.write(30000); // 寫出第4個字元,中文編碼表中30000對應一個漢字。
        /*【注意】關閉資源時,與FileOutputStream不同。 如果不關閉,資料只是儲存到緩衝區,並未儲存到檔案。 */
        fw.close(); 
    } 
}
輸出結果: 
abc田

小貼士:

  1. 雖然引數為int型別四個位元組,但是隻會保留一個字元的資訊寫出。
  2. 如果未呼叫close方法,資料只是儲存到了緩衝區,並未寫出到檔案中。
  • 寫出字元陣列 : write(char[] cbuf) 和 write(char[] cbuf, int off, int len) ,每次可以寫出字元陣列中的資料,用法類似FileOutputStream,程式碼使用演示:
public class FWWrite { 
    public static void main(String[] args) throws IOException { 
        // 使用檔名稱建立流物件
        FileWriter fw = new FileWriter("fw.txt"); 
        // 字串轉換為位元組陣列 
        char[] chars = "張三李四王五".toCharArray(); 
        // 寫出字元陣列 
        fw.write(chars); // 張三李四王五
        // 寫出從索引2開始,2個位元組。索引2是'李',兩個位元組,也就是'李四'。 
        fw.write(b,2,2); // 李四 
        // 關閉資源 
        fos.close(); 
    } 
}
  • 寫出字串: write(String str) 和 write(String str, int off, int len) ,每次可以寫出字串中的資料,更為方便,程式碼使用演示:
public class FWWrite { 
    public static void main(String[] args) throws IOException { 
        // 使用檔名稱建立流物件 
        FileWriter fw = new FileWriter("fw.txt"); 
        // 字串 
        String msg = "張三李四王五"; 
        // 寫出字元陣列 
        fw.write(msg); //張三李四王五 
        // 寫出從索引2開始,2個位元組。索引2是'李',兩個位元組,也就是'李四'。          
        fw.write(msg,2,2); // 李四     
        //關閉資源 
        fos.close(); 
    } 
}
  • 續寫和換行:操作類似於FileOutputStream。
public class FWWrite { 
    public static void main(String[] args) throws IOException { 
        // 使用檔名稱建立流物件,可以續寫資料 
        FileWriter fw = new FileWriter("fw.txt",true); 
        // 寫出字串 
        fw.write("張三"); 
        // 寫出換行 
        fw.write("\r\n"); 
        // 寫出字串 
        fw.write("李四"); 
        // 關閉資源 
        fw.close(); 
    } 
}
輸出結果:
張三
李四

關閉和重新整理

  因為內建緩衝區的原因,如果不關閉輸出流,無法寫出字元到檔案中。但是關閉的流物件,是無法繼續寫出資料的。如果既想寫出資料,又想繼續使用流,就需要 flush 方法了。
  • flush :重新整理緩衝區,流物件可以繼續使用。
  • close :先重新整理緩衝區,然後通知系統釋放資源。流物件不可以再被使用了。

程式碼使用演示:

public class FWWrite { 
    public static void main(String[] args) throws IOException { 
        // 使用檔名稱建立流物件 
        FileWriter fw = new FileWriter("fw.txt");
        // 寫出資料,通過flush 
        fw.write('刷'); // 寫出第1個字元 
        fw.flush(); 
        fw.write('新'); // 繼續寫出第2個字元,寫出成功 
        fw.flush(); 
        // 寫出資料,通過close 
        fw.write('關'); // 寫出第1個字元 
        fw.close(); 
        fw.write('閉'); // 繼續寫出第2個字元,【報錯】java.io.IOException: Stream closed 
        fw.close(); 
    } 
}

小貼士:

  即便是flush方法寫出了資料,操作的最後還是要呼叫close方法,釋放系統資源。

字元輸入流【Reader】

  java.io.Reader 抽象類是表示用於讀取字元流的所有類的超類,可以讀取字元資訊到記憶體中。它定義了字元輸入流的基本共性功能方法。
  • public void close() :關閉此流並釋放與此流相關聯的任何系統資源。
  • public int read() : 從輸入流讀取一個字元。
  • public int read(char[] cbuf) : 從輸入流中讀取一些字元,並將它們儲存到字元陣列 cbuf中 。

FileReader類

  java.io.FileReader 類是讀取字元檔案的便利類。構造時使用系統預設的字元編碼和預設位元組緩衝區。

小貼士:

  1. 字元編碼:位元組與字元的對應規則。Windows系統的中文編碼預設是GBK編碼表。idea中是UTF-8。
  2. 位元組緩衝區:一個位元組陣列,用來臨時儲存位元組資料。

構造方法

  • FileReader(File file) : 建立一個新的 FileReader ,給定要讀取的File物件。
  • FileReader(String fileName) : 建立一個新的 FileReader ,給定要讀取的檔案的名稱。
  當你建立一個流物件時,必須傳入一個檔案路徑,類似於FileInputStream 。

構造舉例,程式碼如下:

public class FileReaderConstructor throws IOException{ 
    public static void main(String[] args) { 
        // 使用File物件建立流物件 
        File file = new File("a.txt");
        FileReader fr = new FileReader(file); 
        // 使用檔名稱建立流物件 
        FileReader fr = new FileReader("b.txt"); 
    } 
}

讀取字元資料

  • 讀取字元: read ()方法,每次可以讀取一個字元的資料,提升為int型別,讀取到檔案末尾,返回 -1 ,迴圈讀取,程式碼使用演示:
public class FRRead { 
    public static void main(String[] args) throws IOException { 
        // 使用檔名稱建立流物件 ,檔案內容:張三李四王五
        FileReader fr = new FileReader("read.txt"); 
        // 定義變數,儲存資料
        int b ; 
        // 迴圈讀取 
        while ((b = fr.read())!=‐1) { 
            System.out.println((char)b); 
        }
        // 關閉資源 
        fr.close(); 
    } 
}
輸出結果: 
張
三
李
四
王
五

小貼士:

  雖然讀取了一個字元,但是會自動提升為int型別。
  • 使用字元陣列讀取: read(char[] cbuf) ,每次讀取b的長度個字元到陣列中,返回讀取到的有效字元個數,讀取到末尾時,返回 -1 ,程式碼使用演示:
public class FISRead { 
    public static void main(String[] args) throws IOException {
        // 使用檔名稱建立流物件 ,檔案內容:張三李四王五
        FileReader fr = new FileReader("read.txt"); 
        // 定義變數,儲存有效字元個數
        int len ; 
        // 定義字元陣列,作為裝字元資料的容器 
        char[] cbuf = new char[2]; 
        // 迴圈讀取 
        while ((len = fr.read(cbuf))!=‐1) { 
            System.out.println(new String(cbuf,0,len)); 
        }
        // 關閉資源 
        fr.close(); 
    }
}
輸出結果: 
張三
李四
王五


總結

  這次主要寫了IO流的體系分類,以及裡面主要的位元組流和字元流中的File節點流的一些基本的寫出和讀取資料的方法實現,其他的節點流(還有處理流)我也會持續更新。除此之外,還差IO流中緩衝流效率對比也會更新。