Java I/O系統 字符流

IO流:用於處理設備上的數據。設計模式

            設備:硬盤,內存,鍵盤錄入。數組

 

IO有具體的分類:app

    1:根據處理的數據類型不一樣,字節流和字符流。函數

    2:根據流向不一樣,輸入流和輸出流。學習

 

字符流的由來:優化

    由於文件編碼的不一樣,而有了對字符進行高效操做的字符流對象。ui

    原理:其實就是基於字節流讀取字節時,去查了指定的碼錶。this

 

字節流和字符流的區別:編碼

    1:字節流讀取的時候,讀到一個字節就返回一個字節。設計

         字符流使用了字節流讀到一個或多個字節(中文對應的字節數是兩個,在UTF-8碼錶中是3個字節)時。先去查指定的編碼表,將查到的字符返回。

    2:字節流能夠處理全部類型的數據,如圖片,mp3,avi。

         而字符流只能處理字符數據。

結論:只要是處理純文本數據,就要優先考慮使用字符流。除此以外都用字節流。

 

IO的體系。所具有的基本功能就是兩個:讀和寫。

    1:字節流

        InputStream(讀),OutputStream(寫)。

    2:字符流

        Reader(讀),Writer(寫)。

 

 

基本的讀寫操做方式:

        由於數據一般都以文件形式存在。

        因此就要找到IO體系中能夠用於操做文件的流對象。

        經過名稱能夠更容易獲取該對象。

        由於IO體系中的子類名後綴絕大部分是父類名稱。而前綴都是體現子類功能的名稱。

 

        Reader

                InputStreamReader

                        FileReader:專門用於處理文件的字符讀取流對象。

        Writer

                OutputStreamWriter

                        FileWriter:專門用於處理文件的字符寫入流對象。

 

        Reader中的常見的方法:

                1:int  read():

                        讀取一個字符。返回的是讀到的那個字符。若是讀到流的末尾,返回-1.

                2:int read(char[]):

                        將讀到的字符存入指定的數組中,返回的是讀到的字符個數,也就是往數組裏裝的元素的個數。若是讀到流的末尾,返回-1.

                3:close():

                        讀取字符其實用的是window系統的功能,就但願使用完畢後,進行資源的釋放。

 

        Writer 中的常見的方法:

                1:write(ch):將一個字符寫入到流中。

                2:write(char[]):將一個字符數組寫入到流中。

                3:write(String):將一個字符串寫入到流中。

                4:flush():刷新流,將流中的數據刷新到目的地中,流還存在。

                5:close():關閉資源:在關閉前會先調用flush(),刷新流中的數據去目的地。而後流關閉。

        

        FileWriter:

                該類沒有特有的方法。只有本身的構造函數。

                該類特色在於,

                1:用於處理文本文件。

                2:該類中有默認的編碼表,

                3:該類中有臨時緩衝。

    

                構造函數:在寫入流對象初始化時,必需要有一個存儲數據的目的地。

                FileWriter(String filename):

                該構造函數作了什麼事情呢?

                1:調用系統資源。

                2:在指定位置,建立一個文件。

                        注意:若是該文件已存在,將會被覆蓋。

                FileWriter(String filename,boolean append):

                        該構造函數:當傳入的boolean類型值爲true時,會在指定文件末尾處進行數據的續寫。

 

 

        FileReader:

                1:用於讀取文本文件的流對象。

                2:用於關聯文本文件。

                

                構造函數:在讀取流對象初始化的時候,必需要指定一個讀取的文件。

                            若是該文件不存在會發生FileNotFoundException.

                FileReader(String filename);

        

        清單 1:

        1:將文本數據存儲到一個文件中。

            

            對於讀取或者寫入流對象的構造函數,以及讀寫方法,還有刷新關閉功能都會拋出IOException或其子類。

 

            因此都要進行處理。或者throws拋出,或者 try    catch 處理。

 

            清單 2:

            完整的異常處理方法。

            

 

 

 

            清單 3:

            讀取一個已有的文本文件,將文本數據打印出來。

            

             一次讀一個字符就打印出來,效率不高。

            

 

 

            讀一個字符就存入字符數組裏,讀完1kb 再打印。

            

 

 

    字符流的緩衝區:

    

            緩衝區的出現提升了對流的操做效率。

            原理:其實就是將數組進行封裝。

            對應的對象:

            BufferedWriter:

                      特有方法:

                            newLine():跨平臺的換行符。

            BufferedReader:

                      特有方法:

                            readLine():一次讀一行,到行標記時,將行標記以前的字符數據做爲字符串返回。當讀到末尾時,返回 null.

 

            在使用緩衝區對象時,要明確,緩衝的存在是爲了加強流的功能二存在,

            因此在創建緩衝區對象時,要先有流對象存在。

            其實緩衝內部就是在使用流對象的方法,只不過加入了數組對數據進行了臨時存儲。爲了提升操做數據的效率。

 

 

        代碼上的體現:

                寫入緩衝區對象。

                //創建緩衝區對象必須把流對象做爲參數傳遞給緩衝區的構造函數。

                BufferedWriter  bufw = new BufferedWriter(new FileWriter("buf.txt"));

                bufw.write("abce");//將數據寫入到了緩衝區。

                bufw.flush();//對緩衝區的數據進行刷新。將數據刷到目的地中。

                bufw.close();//關閉緩衝區,其實關閉的是被包裝在內部的流對象。

 

 

                讀取緩衝區對象。

                BufferedReader  bufr = new BufferedReader(new FileReader("buf.txt"));

                String line = null;

 

                //按照行的形式取出數據。取出的每個行數據不包含回車符。

                while((line=bufr.readLine())!=null)

                {

                    System.out.println(line);

                }

                bufr.close();

 

                練習:經過緩衝區的形式,對文本文件進行拷貝。

                        

                        public static void main(String[] args) {

                                    BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));

                                    BufferedWriter  bufw = new BufferedWriter(new FileWriter("b.txt"));

                                    String line = null;

                                    while((line = bufr.readLine())!= null)  {

                                            bufw.write(line);

                                            bufw.newLine();

                                            bufw.flush();

                                    }

                                    bufw.close();

                                    bufr.close();

                        }

 

                readLine():方法的原理:

                        其實緩衝區中的該方法,用的仍是與緩衝區關聯的流對象的read 方法。

                        只不過,每一次讀到一個字符,先不進行具體操做,先進行臨時存儲。

                        當讀取到回車標識時,將臨時容器中存儲的數據一次性返回。

 

                        既然明確了原理,咱們也能夠實現一個相似功能的方法。

                        class  MyBufferedReader  {

                                 private  Reader  r;

                                 MyBufferedReader(Reader r) {

                                            this.r = r;

                                    }

                                 public  String myReadLine()  throws  IOException  {

                                            //1:建立臨時容器。

                                            StringBuilder sb = new StringBuilder();

                                            //2:循環的使用read方法不斷讀取字符。

                                             int ch = 0 ;

                                             while((ch = r.read())!=-1) {

                                                        if(ch == '\r')

                                                                continue;

                                                        if(ch == '\n')

                                                                 return sb.toString

                                                        else 

                                                                 sb.append((char)ch);

                                                }

                                                if(sb.length()!=0)

                                                        return sb.toString();

 

                                                return  null;

                                            }

 

                                            public  void  myClose()  throws IOException   {

                                                       r.close();

                                            }

                                }

 

 

 

                                main()   {

                                               MyBufferedReader myBufr = new MyBufferedReader(new  FileReader("a.txt"));

                                               String line = null;

 

                                                while((line = myBufr.myReadLine())!=null)  {

                                                                System.out.println(line);

                                                }

                                }

 

                                它的出現基於流並加強了流的功能。

                                這也是一種設計模式的體現:裝飾設計模式。

                                對一組對象進行功能的加強。

 

                                該模式和繼承有什麼區別呢?

                                它比繼承有更好的靈活性。

 

                                一般裝飾類和被裝飾類都同屬於一個父類或者接口。

 

                                Writer

                                        --->MediaWriter

                                        --->TextWriter

 

                                (注:MediaWriter 與 TextWtiter 兩個類在 JDK中並不存在,爲了更形象的舉例說明而「建立」的 ,不要誤解哈。)

                                需求:想要對數據的操做提升效率,就用到了緩衝技術。

                                        經過所學習的繼承特性。能夠創建子類複寫父類的write方法。便可

 

 

 

                                Writer:(注:不要誤解,如下兩個對象不存在,只爲舉例。)

                                        --->MediaWriter

                                                    --->BufferedMediaWriter

                                        --->TextWriter

                                                    --->BufferedTextWriter

 

                                當 Writer 中子類對象過多,那麼爲了提升每個對象效率,每個對象都有一個本身的子類Buffered。

                                雖然能夠實現,可是繼承體系變的很臃腫。

 

                                那麼是否能夠對其進行一下優化呢?

                                其實子類都是在使用緩衝技術。

                                可不能夠對緩衝技術進行描述,將須要加強的對象傳遞給緩衝區便可。

 

                                class BufferedWriter  {

                                         BufferedWriter(MediaWriter mw)   {}

                                         BufferedWriter(TextWriter mw)    {}

                                }

 

 

                                該類雖然完成了對已有兩個對象的加強。

                                可是當有新的對象出現時,仍是繼續在該類中添加構造函數。這樣不利於擴展和維護。

                                將對這些對象父類型進行操做便可。這就是多態,提升了程序的擴展性。

 

                                同時BufferedWriter 中同樣具備write方法,只不過是加強後的write。

                                因此BufferedWriter也應該是Writer中的一個子類。

                                class BufferedWriter extends Writer  {

                                        private Write w;

                                        BufferedWriter(Writer w) {

                                                        this.w = w;

                                        }

                                 }

 

 

                                Writer

                                        --->MediaWriter

                                        --->TextWriter

                                        --->BufferedWriter

                                這樣就會發現裝飾設計模式,優化加強功能的部分。比繼承要靈活不少。

 

 

 

 

能夠在讀一行的基礎上添加一個行號。

class   MyLineNumberReader  extends  MyBufferedReader  {

            private int number;

            MyLineNumberReader(Reader r) {

                super(r);

            }

            public String myReadLine(){

                number++;

                return super.myReadLine();

            }

 

            public void setNumber(int number)  {

                        this.number = number;

            }

 

            public  int  getNumber()  {

                        return  number;

            }

}

相關文章
相關標籤/搜索