天天看點

Java中的IO流,位元組流及字元流 的知識點總結

今日内容介紹

1、位元組流

2、字元流

=======================第一節課開始=============================================

01輸入和輸出

* A:輸入和輸出
    * a: 參照物
        * 到底是輸入還是輸出,都是以Java程式為參照
    * b: Output
        * 把記憶體中的資料存儲到持久化裝置上這個動作稱為輸出(寫)Output操作
        * 程式到檔案稱為輸出
    * c: Input
        * 把持久裝置上的資料讀取到記憶體中的這個動作稱為輸入(讀)Input操作
        * 檔案到程式稱為輸入
    * d: IO操作
        * 把上面的這種輸入和輸出動作稱為IO操作
           

02位元組輸出流OutputStream

* A: 位元組輸出流OutputStream
    * a.概念
        * IO流用來處理裝置之間的資料傳輸
        * Java對資料的操作是通過流的方式
        * Java用于操作流的類都在IO包中
        * 流按流向分為兩種:輸入流,輸出流。
        * 流按操作類型分為兩種:
            * 位元組流 : 位元組流可以操作任何資料,因為在計算機中任何資料都是以位元組的形式存儲的
            * 字元流 : 字元流隻能操作純字元資料,比較友善。
    * b.IO流常用父類
        * 位元組流的抽象父類:
            * InputStream 
            * OutputStream
        * 字元流的抽象父類:
            * Reader 
            * Writer        
    * c.IO程式書寫
        * 使用前,導入IO包中的類
        * 使用時,進行IO異常處理
        * 使用後,釋放資源
    * d: 方法介紹
        *  void close(): 關閉此輸出流并釋放與此流有關的所有系統資源。
        *  void write(byte[] b): 将 b.length 個位元組從指定的 byte 數組寫入此輸出流
        *  void write(byte[] b, int off, int len) :将指定 byte 數組中從偏移量 off 開始的 len 個位元組寫入此輸出流。
        * abstract  void write(int b) : 将指定的位元組寫入此輸出流。
           

03位元組輸出流FileOutputStream寫位元組

* A: 位元組輸出流FileOutputStream寫位元組
    * a: FileOutputStream
        * 寫入資料檔案,學習父類方法,使用子類對象
    * b: FileOutputStream構造方法
        * 作用:綁定輸出的輸出目的
        * FileOutputStream(File file) 
            * 建立一個向指定 File 對象表示的檔案中寫入資料的檔案輸出流。
        * FileOutputStream(File file, boolean append) 
            * 建立一個向指定 File 對象表示的檔案中寫入資料的檔案輸出流,以追加的方式寫入。
        * FileOutputStream(String name) 
            * 建立一個向具有指定名稱的檔案中寫入資料的輸出檔案流。
        * FileOutputStream(String name, boolean append) 
            * 建立一個向具有指定 name 的檔案中寫入資料的輸出檔案流,以追加的方式寫入。
    * c: 流對象使用步驟
        *  1. 建立流子類的對象,綁定資料目的
        *  2. 調用流對象的方法write寫
        *  3. close釋放資源
    * d: 注意事項
        * 流對象的構造方法,可以建立檔案,如果檔案存在,直接覆寫

    * e: 案例代碼

        /*
         *   FileOutputStream
         *   寫入資料檔案,學習父類方法,使用子類對象
         *   
         *   子類中的構造方法: 作用:綁定輸出的輸出目的
         *     參數:
         *       File    封裝檔案
         *       String  字元串的檔案名
         *   
         *   流對象使用步驟
         *     1. 建立流子類的對象,綁定資料目的
         *     2. 調用流對象的方法write寫
         *     3. close釋放資源
         *     
         *    流對象的構造方法,可以建立檔案,如果檔案存在,直接覆寫
         */
        public class FileOutputStreamDemo {
            public static void main(String[] args)throws IOException {
                FileOutputStream fos = new FileOutputStream("c:\\a.txt");
                //流對象的方法write寫資料
                //寫1個位元組
                fos.write(97);
                //關閉資源
                fos.close();

            }
        }
           

04位元組輸出流FileOutputStream寫位元組數組

* A: 位元組輸出流FileOutputStream寫位元組數組
    * a: 方法介紹
        *  void write(byte[] b): 将 b.length 個位元組從指定的 byte 數組寫入此輸出流
        *  void write(byte[] b, int off, int len) :将指定 byte 數組中從偏移量 off 開始的 len 個位元組寫入此輸出流。
    * b: 案例代碼
        /*
         *   FileOutputStream
         *   寫入資料檔案,學習父類方法,使用子類對象
         *   
         *   子類中的構造方法: 作用:綁定輸出的輸出目的
         *     參數:
         *       File    封裝檔案
         *       String  字元串的檔案名
         *   
         *   流對象使用步驟
         *     1. 建立流子類的對象,綁定資料目的
         *     2. 調用流對象的方法write寫
         *     3. close釋放資源
         *     
         *    流對象的構造方法,可以建立檔案,如果檔案存在,直接覆寫
         */
        public class FileOutputStreamDemo {
            public static void main(String[] args)throws IOException {
                FileOutputStream fos = new FileOutputStream("c:\\a.txt");
                //流對象的方法write寫資料
                //寫位元組數組
                byte[] bytes = {65,66,67,68};
                fos.write(bytes);

                //寫位元組數組的一部分,開始索引,寫幾個
                fos.write(bytes, 1, 2);

                //寫入位元組數組的簡便方式
                //寫字元串
                fos.write("hello".getBytes());

                //關閉資源
                fos.close();

            }
        }
           

05檔案的續寫和換行符号

* A: 檔案的續寫和換行符号
    * a: 檔案的續寫
        *  FileOutputStream構造方法, 的第二個參數中,加入true
    * b: 換行符号
        * 在檔案中,寫入換行,符号換行  \r\n
        * \r\n 可以寫在上一行的末尾, 也可以寫在下一行的開頭
    * c: 案例代碼
            /*
             *  FileOutputStream 檔案的續寫和換行問題
             *  續寫: FileOutputStream構造方法, 的第二個參數中,加入true
             *  在檔案中,寫入換行,符号換行  \r\n
             *  \r\n 可以寫在上一行的末尾, 也可以寫在下一行的開頭
             */
            public class FileOutputStreamDemo1 {
                public static void main(String[] args)throws IOException {
                    File file = new File("c:\\b.txt");
                    FileOutputStream fos = new FileOutputStream(file,true);
                    fos.write("hello\r\n".getBytes());
                    fos.write("world".getBytes());
                    fos.close();
                }
            }
           

06IO中的異常處理

* A: IO中的異常處理
    * a:IO流的異常處理
        * try catch finally

    * b: 細節
        * 1. 保證流對象變量,作用域足夠
        * 2. catch裡面,怎麼處理異常
            * 輸出異常的資訊,目的看到哪裡出現了問題
            * 停下程式,從新嘗試
        * 3. 如果流對象建立失敗了,需要關閉資源嗎
            * new 對象的時候,失敗了,沒有占用系統資源
            * 釋放資源的時候,對流對象判斷null
            * 變量不是null,對象建立成功,需要關閉資源

    * c: 案例代碼
        public class FileOutputStreamDemo3 {
            public static void main(String[] args) {
                //try 外面聲明變量,try 裡面建立對象
                FileOutputStream fos = null;
                try{
                    fos = new FileOutputStream("s:\\a.txt");
                    fos.write(100);
                }catch(IOException ex){
                    System.out.println(ex);
                    throw new RuntimeException("檔案寫入失敗,重試");
                }finally{
                    try{
                        if(fos!=null)
                          fos.close();
                    }catch(IOException ex){
                        throw new RuntimeException("關閉資源失敗");
                    }
                }
            }
        }
           

07位元組輸入流InputStream

* A: 位元組輸入流InputStream
    * a: 方法介紹
        * abstract  int read() :
            * 從輸入流中讀取資料的下一個位元組。
        * int read(byte[] b)  
            * 從輸入流中讀取一定數量的位元組,并将其存儲在緩沖區數組 b 中。
        * int read(byte[] b, int off, int len) 
            * 将輸入流中最多 len 個資料位元組讀入 byte 數組。
        * void close() 
            * 關閉此輸入流并釋放與該流關聯的所有系統資源。


    * b: 案例代碼
        /*
         *   位元組輸入流
         *     java.io.InputStream 所有位元組輸入流的超類
         *   作用: 讀取任意檔案,每次隻讀取1個位元組
         *   讀取的方法  read
         *     int  read() 讀取1個位元組
         *     int  read(byte[] b) 讀取一定量的位元組,存儲到數組中
         */
        public class InputStreamDemo {

        }
           

08位元組輸入流FileInputStream讀取位元組

* A: 位元組輸入流FileInputStream讀取位元組
    * a: 方法介紹
        * abstract  int read() :
            * 從輸入流中讀取資料的下一個位元組,傳回-1表示檔案結束
        * int read(byte[] b)  
            * 從輸入流中讀取一定數量的位元組,并将其存儲在緩沖區數組 b 中。
            * 讀入緩沖區的位元組總數,如果因為已經到達檔案末尾而沒有更多的資料,則傳回 -1。
        * int read(byte[] b, int off, int len) 
            * 将輸入流中最多 len 個資料位元組讀入 byte 數組。
        * void close() 
            * 關閉此輸入流并釋放與該流關聯的所有系統資源。
    * b: 案例代碼
        /*
         *  FileInputStream讀取檔案
         *  
         *  構造方法: 為這個流對象綁定資料源
         *  
         *    參數: 
         *      File 類型對象
         *      String 對象
         *   輸入流讀取檔案的步驟
         *     1. 建立位元組輸入流的子類對象
         *     2. 調用讀取方法read讀取
         *     3. 關閉資源
         *     
         *     read()方法,
         *       read()執行一次,就會自動讀取下一個位元組
         *       傳回值,傳回的是讀取到的位元組, 讀取到結尾傳回-1
         */
        public class FileInputStreamDemo {
            public static void main(String[] args) throws IOException{
                FileInputStream fis = new FileInputStream("c:\\a.txt");
                //讀取一個位元組,調用方法read 傳回int
                //使用循環方式,讀取檔案,  循環結束的條件  read()方法傳回-1
                int len = 0;//接受read方法的傳回值

                while( (len = fis.read()) != -1){
                    System.out.print((char)len);
                }
                //關閉資源
                fis.close();
            }
        }

        /*
         * int i = fis.read();
                System.out.println(i);

                i = fis.read();
                System.out.println(i);

                i = fis.read();
                System.out.println(i);

                i = fis.read();
                System.out.println(i);
         */
           

09位元組輸入流FileInputStream讀取位元組數組

* A: 位元組輸入流FileInputStream讀取位元組數組
    * a: 方法介紹
        * int read(byte[] b)  
            * 從輸入流中讀取一定數量的位元組,并将其存儲在緩沖區數組 b 中。
            * 讀入緩沖區的位元組總數,如果因為已經到達檔案末尾而沒有更多的資料,則傳回 -1。
        * int read(byte[] b, int off, int len) 
            * 将輸入流中最多 len 個資料位元組讀入 byte 數組。
    * b: 案例代碼
        /*
         *  FileInputStream讀取檔案
         *   讀取方法  int read(byte[] b) 讀取位元組數組
         *   數組作用: 緩沖的作用, 提高效率
         *   read傳回的int,表示什麼含義 讀取到多少個有效的位元組數
         */
        public class FileInputStreamDemo1 {
            public static void main(String[] args) throws IOException {
                FileInputStream fis = new FileInputStream("c:\\a.txt");
                // 建立位元組數組
                byte[] b = new byte[2];

                int len = fis.read(b);
                System.out.println(new String(b));// ab
                System.out.println(len);// 2

                len = fis.read(b);
                System.out.println(new String(b));// cd
                System.out.println(len);// 2

                len = fis.read(b);
                System.out.println(new String(b));// ed
                System.out.println(len);// 1

                len = fis.read(b);
                System.out.println(new String(b));// ed
                System.out.println(len);// -1

                fis.close();
            }
        }
           

10位元組輸入流FileInputStream讀取位元組數組的實作原理

* A:位元組輸入流FileInputStream讀取位元組數組的實作原理
    * a: 原理
        * 參見day23_source檔案夾中的"讀取數組的原理.jpg"


    * b: 案例代碼

        public class FileInputStreamDemo1 {
            public static void main(String[] args) throws IOException {
                FileInputStream fis = new FileInputStream("c:\\a.txt");
                //建立位元組數組
                byte[] b = new byte[1024];

                int len = 0 ;
                while( (len = fis.read(b)) !=-1){
                    System.out.print(new String(b,0,len));
                }
                fis.close();
            }
        }
           

11檔案複制原理

* A: 檔案複制原理
    * a: 見day23_source/檔案複制原理.jpg
           

12位元組流複制檔案讀取單個位元組

* A: 位元組流複制檔案讀取單個位元組
    * a: 案例代碼
        /*
         *  将資料源 c:\\a.txt
         *  複制到 d:\\a.txt  資料目的
         *  位元組輸入流,綁定資料源
         *  位元組輸出流,綁定資料目的
         *  
         *  輸入,讀取1個位元組
         *  輸出,寫1個位元組
         */
        public class Copy {
            public static void main(String[] args) {
                //定義兩個流的對象變量
                FileInputStream fis = null;
                FileOutputStream fos = null;
                try{
                    //建立兩個流的對象,綁定資料源和資料目的
                    fis = new FileInputStream("c:\\t.zip");
                    fos = new FileOutputStream("d:\\t.zip");
                    //位元組輸入流,讀取1個位元組,輸出流寫1個位元組
                    int len = 0 ;
                    while((len = fis.read())!=-1){
                        fos.write(len);
                    }
                }catch(IOException ex){
                    System.out.println(ex);
                    throw new RuntimeException("檔案複制失敗");
                }finally{
                    try{
                        if(fos!=null)
                            fos.close();
                    }catch(IOException ex){
                        throw new RuntimeException("釋放資源失敗");
                    }finally{
                        try{
                            if(fis!=null)
                                fis.close();
                        }catch(IOException ex){
                            throw new RuntimeException("釋放資源失敗");
                        }
                    }
                }
            }
        }
           

13位元組流複制檔案讀取位元組數組

* A: 位元組流複制檔案讀取位元組數組
    * a: 案例代碼
        /*
         *  位元組流複制檔案
         *   采用數組緩沖提高效率
         *   位元組數組
         *   FileInputStream 讀取位元組數組
         *   FileOutputStream 寫位元組數組
         */
        public class Copy_1 {
            public static void main(String[] args) {
                long s = System.currentTimeMillis();
                FileInputStream fis = null;
                FileOutputStream fos = null;
                try{
                    fis = new FileInputStream("c:\\t.zip");
                    fos = new FileOutputStream("d:\\t.zip");
                    //定義位元組數組,緩沖
                    byte[] bytes = new byte[1024*10];
                    //讀取數組,寫入數組
                    int len = 0 ; 
                    while((len = fis.read(bytes))!=-1){
                        fos.write(bytes, 0, len);
                    }
                }catch(IOException ex){
                    System.out.println(ex);
                    throw new RuntimeException("檔案複制失敗");
                }finally{
                    try{
                        if(fos!=null)
                            fos.close();
                    }catch(IOException ex){
                        throw new RuntimeException("釋放資源失敗");
                    }finally{
                        try{
                            if(fis!=null)
                                fis.close();
                        }catch(IOException ex){
                            throw new RuntimeException("釋放資源失敗");
                        }
                    }
                }
                long e = System.currentTimeMillis();
                System.out.println(e-s);
            }
        }
           

14編碼表

* A: 編碼表
    * a: 定義:
        * 生活中字元和計算機二進制的對應關系表,就是編碼表
    * b: 分類
        * 1、ascii: 一個位元組中的7位就可以表示。對應的位元組都是正數。0-xxxxxxx
        * 2、iso-8859-1:拉丁碼表 latin,用了一個位元組用的8位。1-xxxxxxx  負數。
        * 3、GB2312:簡體中文碼表。包含6000-7000中文和符号。用兩個位元組表示。兩個位元組第一個位元組是負數,第二個位元組可能是正數
            * GBK:目前最常用的中文碼表,2萬的中文和符号。用兩個位元組表示,其中的一部分文字,第一個位元組開頭是1,第二位元組開頭是0
            * GB18030:最新的中文碼表,目前還沒有正式使用。
        * 4、unicode:國際标準碼表:無論是什麼文字,都用兩個位元組存儲。
            * Java中的char類型用的就是這個碼表。char c = 'a';占兩個位元組。
            * Java中的字元串是按照系統預設碼表來解析的。簡體中文版 字元串預設的碼表是GBK。
        * 5、UTF-8:基于unicode,一個位元組就可以存儲資料,不要用兩個位元組存儲,而且這個碼表更加的标準化,在每一個位元組頭加入了編碼資訊(後期到api中查找)。
        * 6、能識别中文的碼表:GBK、UTF-8;正因為識别中文碼表不唯一,涉及到了編碼解碼問題。
            * 對于我們開發而言;常見的編碼 GBK  UTF-8  ISO-8859-1
            * 文字--->(數字) :編碼。 “abc”.getBytes()  byte[]
            * (數字)--->文字  : 解碼。 byte[] b={97,98,99}  new String(b) 
           

15字元輸出流寫文本FileWriter類

* A: 字元輸出流寫文本FileWriter類
    * a: 方法介紹
        *  void write(int c)
            *  寫入單個字元
        * void write(String str)  
            * 寫入字元串
        * void write(String str, int off, int len) 
            * 寫入字元串的某一部分
        * void write(char[] cbuf)  
            * 寫入字元數組
        * abstract  void write(char[] cbuf, int off, int len)  
            *  寫入字元數組的某一部分
    * b: 案例代碼
        /*
         *   字元輸出流
         *     java.io.Writer 所有字元輸出流的超類
         *   寫檔案,寫文本檔案
         *   
         *   寫的方法 write
         *     write(int c) 寫1個字元
         *     write(char[] c)寫字元數組
         *     write(char[] c,int,int)字元數組一部分,開始索引,寫幾個
         *     write(String s) 寫入字元串
         *     
         *   Writer類的子類對象 FileWriter
         *   
         *   構造方法:  寫入的資料目的
         *     File 類型對象
         *     String 檔案名
         *     
         *   字元輸出流寫資料的時候,必須要運作一個功能,重新整理功能
         *   flush()
         */
        public class WriterDemo {
            public static void main(String[] args) throws IOException{
                FileWriter fw = new FileWriter("c:\\1.txt");

                //寫1個字元
                fw.write(100);
                fw.flush();

                //寫1個字元數組
                char[] c = {'a','b','c','d','e'};
                fw.write(c);
                fw.flush();

                //寫字元數組一部分
                fw.write(c, 2, 2);
                fw.flush();

                //寫如字元串
                fw.write("hello");
                fw.flush();

                fw.close();
            }
        }
           

16字元輸入流讀取文本FileReader類

* A: 字元輸入流讀取文本FileReader類
    * a: 方法介紹
        *  int read() 
            * 讀取單個字元
        * int read(char[] cbuf) 
            * 将字元讀入數組
        * abstract  int read(char[] cbuf, int off, int len)  
            * 将字元讀入數組的某一部分。
    * b: 案例代碼
        /*
         *  字元輸入流讀取文本檔案,所有字元輸入流的超類
         *    java.io.Reader
         *  專門讀取文本檔案
         *  
         *  讀取的方法 : read()
         *   int read() 讀取1個字元
         *   int read(char[] c) 讀取字元數組
         *   
         *   Reader類是抽象類,找到子類對象 FileReader
         *   
         *   構造方法: 綁定資料源
         *     參數:
         *        File  類型對象
         *        String檔案名
         */
        public class ReaderDemo {
            public static void main(String[] args) throws IOException{
                FileReader fr = new FileReader("c:\\1.txt");
                /*int len = 0 ;
                while((len = fr.read())!=-1){
                    System.out.print((char)len);
                }*/
                char[] ch = new char[1024];
                int len = 0 ;
                while((len = fr.read(ch))!=-1){
                    System.out.print(new String(ch,0,len));
                }

                fr.close();
            }
        }
           

17flush方法和close方法差別

* A: flush方法和close方法差別
    *a: flush()方法
        * 用來重新整理緩沖區的,重新整理後可以再次寫出,隻有字元流才需要重新整理
    *b: close()方法
        * 用來關閉流釋放資源的的,如果是帶緩沖區的流對象的close()方法,不但會關閉流,還會再關閉流之前重新整理緩沖區,關閉後不能再寫出 
           

18字元流複制文本檔案

* A: 字元流複制文本檔案
    * a: 案例代碼
        /*
         *  字元流複制文本檔案,必須文本檔案
         *  字元流查詢本機預設的編碼表,簡體中文GBK
         *  FileReader讀取資料源
         *  FileWriter寫入到資料目的
         */
        public class Copy_2 {
            public static void main(String[] args) {
                FileReader fr = null;
                FileWriter fw = null;
                try{
                    fr = new FileReader("c:\\1.txt");
                    fw = new FileWriter("d:\\1.txt");
                    char[] cbuf = new char[1024];
                    int len = 0 ;
                    while(( len = fr.read(cbuf))!=-1){
                        fw.write(cbuf, 0, len);
                        fw.flush();
                    }

                }catch(IOException ex){
                    System.out.println(ex);
                    throw new RuntimeException("複制失敗");
                }finally{
                    try{
                        if(fw!=null)
                            fw.close();
                    }catch(IOException ex){
                        throw new RuntimeException("釋放資源失敗");
                    }finally{
                        try{
                            if(fr!=null)
                                fr.close();
                        }catch(IOException ex){
                            throw new RuntimeException("釋放資源失敗");
                        }
                    }
                }
            }
        }
           

19總結

* 把今天的知識點總結一遍。