19. Java中數據的讀寫--IO流

數據的讀寫–IO流

IO概述

  • 當你電腦上插入一個U盤,可以把一個視頻,拷貝到你的電腦硬盤裏。我們把這種數據的傳輸,可以看做是一種數據的流動,按照流動的方向,以內存爲基準,分爲 輸入input 和 輸出output ,即流向內存是輸入流,流出內存的輸出流。

  • Java中I/O操作主要是指使用 java.io 包下的內容,進行輸入、輸出操作。輸入也叫做讀取數據,輸出也叫做作寫出數據。

  • 那麼數據都是在哪些設備上的呢?鍵盤、內存、硬盤、外接設備等等。

IO分類

根據數據的流向分爲:輸入流輸出流

輸入流 :把數據從 其他設備 上讀取到 內存 中的流。

輸出流 :把數據從 內存 中寫出到 其他設備 上的流。

格局數據的類型分爲:字節流字符流

字節流以字節爲單位,讀寫數據的流。

字符流以字符爲單位,讀寫數據的流。

頂級父類們

輸入流 輸出流
字節流 字節輸入流 InputStream 字節輸出流 OutputStream
字符流 字符輸入流 Reader 字符輸出流 Writer

字節流InputStream/OutputStream

​ 一切文件數據(文本、圖片、視頻等)在存儲時,都是以二進制數字的形式保存,都一個一個的字節,那麼傳輸時一樣如此。所以,字節流可以傳輸任意文件數據。在操作流的時候,我們要時刻明確,無論使用什麼樣的流對象,底層傳輸的始終爲二進制數據。

字節輸出流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):將指定的字節輸出流。
FileOutputStream

OutputStream 有很多子類,我們從最簡單的一個子類開始。java.io.FileOutputStream 類是文件輸出流,用於將數據寫出到文件。

構造方法
  • public FileOutputStream(File file) :創建文件輸出流以寫入由指定的 File對象表示的文件。

  • public FileOutputStream(String name): 創建文件輸出流以指定的名稱寫入文件。

  • 當你創建一個流對象時,必須傳入一個文件路徑。該路徑下,如果沒有這個文件,會創建該文件如果有這個文件,會清空這個文件的數據。

    public static void main(String[] args) {
        // 使用File對象創建流對象
        File file = new File("a.txt");
        FileOutputStream fos1 = new FileOutputStream(file);
        
        // 使用文件名稱創建流對象
        FileOutputStream fos2 = new FileOutputStream("b.txt");
    }
寫出字節數據

ASCII字符代碼表

在這裏插入圖片描述

public void write(int b):將指定的字節輸出流。

    public static void main(String[] args) throws IOException {
        // 使用文件名稱創建流對象
        FileOutputStream fos = new FileOutputStream("fos.txt");
        
        // 寫出數據
        fos.write(97); // 寫出第1個字節a
        fos.write(98); // 寫出第2個字節b
        fos.write(99); // 寫出第3個字節c
        // 關閉資源
        fos.close();
    }

public void write(byte[] b):將 b.length字節從指定的字節數組寫入此輸出流。

    public static void main(String[] args) throws IOException {
        
        // 使用文件名稱創建流對象
        FileOutputStream fos = new FileOutputStream("fos.txt");
        
        // 字符串轉換爲字節數組
        byte[] b = "簡維程序員".getBytes();
        
        // 寫出字節數組數據
        fos.write(b);
        
        // 關閉資源
        fos.close();
    }

public void write(byte[] b, int off, int len) :從指定的字節數組寫入len字節,從偏移量off開始輸出到此輸出流。☆

    public static void main(String[] args) throws IOException {
        // 使用文件名稱創建流對象
        FileOutputStream fos = new FileOutputStream("fos.txt");
        // 字符串轉換爲字節數組
        byte[] b = "abcde".getBytes();
        
        // 寫出從索引2開始,2個字節。索引2是c,兩個字節,也就是cd。
        fos.write(b,2,2);
        
        // 關閉資源
        fos.close();
    }
數據的追加
  • public FileOutputStream(File file, boolean append): 創建文件輸出流以寫入由指定的 File對象表示的文件。

  • public FileOutputStream(String name, boolean append): 創建文件輸出流以指定的名稱寫入文件。

  • appendtrue表示追加數據, false表示清空原有數據,不寫默認爲false

  •     //源碼
    	 public FileOutputStream(String name) throws FileNotFoundException {
            this(name != null ? new File(name) : null, false);
        }
    
        public FileOutputStream(File file) throws FileNotFoundException {
            this(file, false);
        }
    
寫出換行

回車符 \r 和換行符 \n :

回車符:回到一行的開頭(return)。

換行符:下一行(newline)。

系統中的換行

  • Windows系統裏,每行結尾是 回車+換行 ,即\r\n

  • Unix系統裏,每行結尾只有換行 ,即 \n

  • Mac系統裏,每行結尾是 回車 ,即 \r

字節輸入流InputStream

java.io.InputStream 抽象類是表示字節輸入流的所有類的超類,可以讀取字節信息到內存中。它定義了字節輸入流的基本共性功能方法。

  • public void close() :關閉此輸入流並釋放與此流相關聯的任何系統資源。
  • public abstract int read(): 從輸入流讀取數據的下一個字節。
  • public int read(byte[] b): 從輸入流中讀取一些字節數,並將它們存儲到字節數組 b中 。
FileInputStream

java.io.FileInputStream 類是文件輸入流,從文件中讀取字節。

構造方法
  • FileInputStream(File file) : 通過打開與實際文件的連接來創建一個 FileInputStream ,該文件由文件系統中的 File對象 file命名。
  • FileInputStream(String name) : 通過打開與實際文件的連接來創建一個 FileInputStream ,該文件由文件系統中的路徑名 name命名。
  • 當你創建一個流對象時,必須傳入一個文件路徑。該路徑下,如果沒有該文件,會拋出 FileNotFoundException
    public static void main(String[] args) {
        // 使用File對象創建流對象
        File file = new File("a.txt");
        FileInputStream fos = new FileInputStream(file);
        // 使用文件名稱創建流對象
        FileInputStream fos = new FileInputStream("b.txt");
    }
讀取字節數據

public int read(): 從輸入流讀取數據的下一個字節。

    public static void main(String[] args) throws IOException{
        FileInputStream fis = new FileInputStream("read.txt");
        // 定義變量,保存數據
        int b ;
            // 循環讀取
            while ((b = fis.read())!=1) {
                System.out.println((char)b);
            }
        // 關閉資源
        fis.close();
    }

public int read(byte[] b): 從輸入流中讀取一些字節數,並將它們存儲到字節數組 b中 。

    public static void main(String[] args) throws IOException{
        // 使用文件名稱創建流對象.
        FileInputStream fis = new FileInputStream("read.txt"); // 文件中爲abcde
        // 定義變量,作爲有效個數
        int len ;
            // 定義字節數組,作爲裝字節數據的容器
            byte[] b = new byte[2];
        // 循環讀取
        while (( len= fis.read(b))!=1) {
            // 每次讀取後,把數組的有效字節部分,變成字符串打印
            System.out.println(new String(b,0,len));// len 每次讀取的有效字節個數
        }
        // 關閉資源
        fis.close();
    }

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

字節流練習–複製圖片

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();
    }
}

字符流Writer/Reader

當使用字節流讀取文本文件時,可能會有一個小問題。就是遇到中文字符時,可能不會顯示完整的字符,那是因爲一箇中文字符可能佔用多個字節存儲。所以Java提供一些字符流類,以字符爲單位讀寫數據,專門用於處理文本文件。

字符輸出流Writer

java.io.Writer 抽象類是表示用於寫出字符流的所有類的超類,將指定的字符信息寫出到目的地。它定義了字節輸出流的基本共性功能方法。

  • public abstract void close() :關閉此輸出流並釋放與此流相關聯的任何系統資源。

  • public abstract void flush():刷新此輸出流並強制任何緩衝的輸出字符被寫出。

  • public void write(int c):寫出一個字符。

  • public void write(char[] cbuf):將 b.length字符從指定的字符數組寫出此輸出流。

  • public abstract void write(char[] b, int off, int len) :從指定的字符數組寫出 len字符,從偏移量off開始輸出到此輸出流。

  • public void write(String str):寫出一個字符串。

FileWriter

java.io.FileWriter類是寫出字符到文件的便利類。構造時使用系統默認的字符編碼和默認字節緩衝區。

構造方法
  • FileWriter(File file) : 創建一個新的 FileWriter,給定要讀取的File對象。
  • FileWriter(String fileName) : 創建一個新的 FileWriter,給定要讀取的文件的名稱。

當你創建一個流對象時,必須傳入一個文件路徑,類似於FileOutputStream

    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");
    }
寫出數據

public void write(int c):寫出一個字符。

【注意】關閉資源時,與FileOutputStream不同。如果不關閉,數據只是保存到緩衝區,並未保存到文件。

    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();
    }
關閉和刷新

因爲內置緩衝區的原因,如果不關閉輸出流,無法寫出字符到文件中。但是關閉的流對象,是無法繼續寫出數據的。如果我們既想寫出數據,又想繼續使用流,就需要 flush 方法了。

  • flush :刷新緩衝區,流對象可以繼續使用。
  • close:關閉流,釋放系統資源。關閉前會刷新緩衝區。
    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();
    }
寫出其它數據

write(char[] cbuf)write(char[] cbuf, int off, int len) ,每次可以寫出字符數組中的數據

    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(chars,2,2); // 程序
        // 關閉資源
        fos.close();
    }

write(String str)write(String str, int off, int len),每次可以寫出字符串中的數據

    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 static void main(String[] args) throws IOException {
        // 使用文件名稱創建流對象,可以續寫數據
        FileWriter fw = new FileWriter("fw.txt"true);
        // 寫出字符串
        fw.write("justweb");
        // 寫出換行
        fw.write("\r\n");
        // 寫出字符串
        fw.write("程序員");
        // 關閉資源
        fw.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 static void main(String[] args) {
        // 使用File對象創建流對象
        File file = new File("a.txt");
        FileReader fr = new FileReader(file);
        // 使用文件名稱創建流對象
        FileReader fr = new FileReader("b.txt");
    }
讀取字符數據

public int read() : 從輸入流讀取一個字符。

    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();
    };

public int read(char[] cbuf) : 從輸入流中讀取一些字符,並將它們存儲到字符數組cbuf中 。

    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));
        }
        // 關閉資源
        fr.close();
    }
	/*
	輸出結果:
        簡維
        程序
        員序
	*/
    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();
    }
	/*
	輸出結果:
        簡維
        程序
        員
	*/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章