国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

黑馬程序員——Java基礎(chǔ)--IO流(一)---字符流和字節(jié)流

2019-11-15 01:12:39
字體:
供稿:網(wǎng)友
黑馬程序員——java基礎(chǔ)--IO流(一)---字符流和字節(jié)流

------Java培訓(xùn)、Android培訓(xùn)、iOS培訓(xùn)、.Net培訓(xùn)、期待與您交流! -------

一、IO流的介紹及體系

IO流用來處理設(shè)備之間的數(shù)據(jù)傳輸。java對(duì)數(shù)據(jù)的操作是通過流的方式。java用于操作流的對(duì)象都在IO包中。

輸入流和輸出流相對(duì)于內(nèi)存設(shè)備而言:將外設(shè)中的數(shù)據(jù)讀取到內(nèi)存中:輸入。將內(nèi)存中的數(shù)據(jù)寫出到外設(shè)中:輸出。

流按照操作數(shù)據(jù)分為兩種:字節(jié)流和字符流。

字符流的由來:其實(shí)就是字節(jié)流讀取文字字節(jié)數(shù)據(jù)后,不直接操作而是先查指定的編碼表,獲取對(duì)應(yīng)的文字,再對(duì)這個(gè)文字進(jìn)行操作。簡單來說:字節(jié)流+編碼表。

字節(jié)流的兩個(gè)基類:InputStream、OutputStream

字符流的兩個(gè)基類:Reader、Writer

由這四個(gè)類派生出來的子類名稱都是以其父類名作為子類名的后綴。

如:InputStream的子類FileInputStream

Reader的子類FlieReader

其中字符流只能操作字符數(shù)據(jù),而字節(jié)流不僅可以操作字符數(shù)據(jù)也可以操作字節(jié)數(shù)據(jù)。字節(jié)流是通用的。

因?yàn)槲覀兘?jīng)常用字符串,所以我們首先介紹一下字符流

二、IO流常用基類----字符流

Reader

  |--BufferedReader:從字符輸入流中讀取文本,緩沖各個(gè)字符,從而實(shí)現(xiàn)字符、數(shù)組和行的高效讀取。

    |--LineNumberReader:跟蹤行號(hào)的緩沖字符輸入流。

  |--InputStreamReader:轉(zhuǎn)換流,字節(jié)通向字符的橋梁。

    |--FileReader:專門用于處理文件的字符讀取流對(duì)象。

Writer

  |--BufferedWriter:將文本寫入字符輸出流,緩沖各個(gè)字符,從而提供單個(gè)字符、數(shù)組和字符串的高效寫入。

  |--OutputStreamWriter:轉(zhuǎn)換流,字符通向字節(jié)的橋梁

    |--FileWriter:專門用于處理文件的字符寫入流對(duì)象。

字符流中的對(duì)象融合了編碼表。使用的是默認(rèn)的編碼,即當(dāng)前系統(tǒng)的編碼。

1、Writer抽象類 寫入字符流的抽象類

(1)、Writer抽象類常用方法

1 void  write(int c);//寫入單個(gè)字符2 void  write(String str);//寫入 字符串3 void  write(String str,int off,int len);//寫入字符串的某一部分4 void  write(char[] cbhf);//寫入字符數(shù)組5 abstract void   write(char[] cbuf,int off,int len);//寫入字符數(shù)組的某一部分6 abstract void   close();//關(guān)閉流,但是會(huì)先刷新它7 abstract void   flush();//刷新該流的緩沖區(qū)

(2)、FileWriter類(Writer抽象類的子類)

  因?yàn)閃riter是抽象的,無法創(chuàng)建對(duì)象。所以我們找到一個(gè)專門用于操作文件的Writer子類對(duì)象:FileWriter。后綴名是父類名,前綴名是該流對(duì)象的功能。該對(duì)象可以直接操作文件。該對(duì)象中沒有特有方法,所以可以直接用Writer中的方法操作文件。但是這個(gè)對(duì)象可以創(chuàng)建對(duì)象,我們用它的構(gòu)造函數(shù)。

1)、FileWriter構(gòu)造方法

1 new  FileWriter(File file);//根據(jù)給定的File對(duì)象構(gòu)造一個(gè) FileWriter 對(duì)象2 new  FileWriter(File file,boolean append);//根據(jù)給定的File對(duì)象構(gòu)造一個(gè) FileWriter 對(duì)象,而且不會(huì)覆蓋3 new  FileWriter(String fileName);//根據(jù)給定的文件名創(chuàng)建FileWriter 對(duì)象4 new  FileWriter(String fileName,boolean append);//對(duì)已有文件的數(shù)據(jù)續(xù)寫

2)、寫入字符流步驟

1.創(chuàng)建一個(gè)FileWriter對(duì)象。該對(duì)象一被初始化就必須明確被操作的文件,而且該文件會(huì)被創(chuàng)建到指定目錄下。如果該目錄下已有同名文件,會(huì)將其覆蓋掉。當(dāng)然可以用new FileWriter(String fileName,true)構(gòu)造方法則將數(shù)據(jù)寫入文件末尾處,這樣就不會(huì)覆蓋原來的文件了。其實(shí)這步就是在明確詩句要存放的目的地。

2.調(diào)用write方法,將字符串寫入到輸出流中。

3.調(diào)用flush方法。刷新流對(duì)象中的緩沖區(qū)數(shù)據(jù),將數(shù)據(jù)刷到指定目的地中。

4.最后一定要記得關(guān)閉流資源。但是在關(guān)閉之前會(huì)刷新一次內(nèi)部的緩沖區(qū)中的數(shù)據(jù)。和flush區(qū)別:flush刷新后,流可以繼續(xù)使用,close刷新后,會(huì)將流關(guān)閉。

注:

1. close方法只能用一次。

2. 流關(guān)閉以后不能,不能再調(diào)用write方法,否則會(huì)報(bào)異常錯(cuò)誤:Stream closed IO異常。

3.由于在創(chuàng)建對(duì)象時(shí),需要指定創(chuàng)建文件位置,如果指定的位置不存在,就會(huì)發(fā)生IOException異常。所以要進(jìn)行異常處理。

需求:在硬盤上,創(chuàng)建一個(gè)文件并寫入一些文字?jǐn)?shù)據(jù)。

 1 import java.io.*; 2 //標(biāo)準(zhǔn)的IO異常處理方法 3 class FileWriterDemo  4 { 5     public static void main(String[] args)  6     { 7         FileWriter fw=null; 8         try 9         {10              //創(chuàng)建一個(gè)可以往文件中寫入字符數(shù)據(jù)的字符輸出流對(duì)象11              //既然是往一個(gè)文件中寫入文字?jǐn)?shù)據(jù),那么在創(chuàng)建對(duì)象時(shí),就必須明確該文件(用于存儲(chǔ)數(shù)據(jù)的目的地)12              //如果文件不存在,則會(huì)自動(dòng)創(chuàng)建,如果文件存在,則會(huì)被覆蓋13             fw=new FileWriter("Demo.txt");14 //            fw=new FileWriter("Demo.txt",true);//傳遞一個(gè)true參數(shù),代表不覆蓋已有的文件。并在已有文件的末尾處進(jìn)行數(shù)據(jù)續(xù)寫。15             16             //調(diào)用Writer對(duì)象中的write(string)方法,寫入數(shù)據(jù)。其實(shí)該數(shù)據(jù)寫到臨時(shí)緩沖區(qū)中        17             fw.write("我愛黑馬程序員");18             19             //刷新緩沖區(qū),將數(shù)據(jù)從緩沖區(qū)寫入到目的地中20             fw.flush();            21         }22         catch (IOException e)23         {24             System.out.PRintln(e);25         }26         finally{27             if(fw!=null)//首先判斷流對(duì)象時(shí)候創(chuàng)建成功28             try29             {30                 //close方法一定要關(guān)閉流資源,一定會(huì)執(zhí)行的代碼放在finally塊中,31                 //close方法在調(diào)用的時(shí)候也會(huì)拋出io異常,所以要單獨(dú)的進(jìn)行try catch處理32                 fw.close();33             }34             catch (IOException e)35             {36                 System.out.println("輸出流關(guān)閉失敗!");37             }38         }39     }40 }
2、Reader抽象類 讀取字符流的抽象類

使用Reader體系,讀取一個(gè)文本文件中的數(shù)據(jù)。返回 -1 ,標(biāo)志讀到結(jié)尾。

(1)、Reader抽象類中的常用方法

1 int  read();//讀取一個(gè)字符2 int  read(char[] cbuf);//將字符讀入數(shù)組3 int  read(char[] cbuf,int off,int len);//將字符讀入數(shù)組的某一部分4 vioid  close();//關(guān)閉該流并釋放與之關(guān)聯(lián)的所有資源。5 void mark(int readAheadLimit);//標(biāo)記流中的當(dāng)前位置6 long  skip(long n);//跳過字符7 void  rest();//重置該流

注意:flush方法只有Writer類中有,Reader中沒有。

(2)、FileReader類(Reader抽象類的子類)

  因?yàn)镽eader是抽象的,無法創(chuàng)建對(duì)象。所以我們找到一個(gè)專門用于操作文件的Reader子類對(duì)象:FileReader。后綴名是父類名,前綴名是該流對(duì)象的功能。該對(duì)象可以直接操作文件。該對(duì)象中沒有特有方法,所以可以直接用Reader中的方法操作文件。但是這個(gè)對(duì)象可以創(chuàng)建對(duì)象,我們用它的構(gòu)造函數(shù)。

1)、FileReader構(gòu)造方法

1 new FileReader();//給定讀取數(shù)據(jù)的文件名創(chuàng)建讀取流對(duì)象2 new FileReader();//給定讀取數(shù)據(jù)的File創(chuàng)建讀取流對(duì)象

2)、讀取字符流步驟

1.創(chuàng)建一個(gè)文件讀取流對(duì)象,和指定名稱的文件相關(guān)聯(lián)。要保證該文件是已經(jīng)存在的,如果不存在,會(huì)發(fā)生異常FileNotFoundException。

2.調(diào)用讀取流對(duì)象的read方法。read():一次讀一個(gè)字符,而且會(huì)自動(dòng)往下讀。如果讀到流的末尾處就返回-1;使用read(char[])方法讀取文本文件數(shù)據(jù)。通過字符數(shù)組進(jìn)行讀取。這種方法比較高效建議用這種方法。

3.調(diào)用close方法關(guān)閉流資源。

需求:讀取一個(gè)文文件,將讀取到的字符打印到控制臺(tái)(FileReader)

第一種讀取方式:使用read()方法單個(gè)讀取文本字符數(shù)據(jù)。

 1 import java.io.*; 2 class FileReaderDemo  3 { 4     public static void main(String[] args)  5     { 6         FileReader fr=null; 7         try 8         { 9             //創(chuàng)建可以讀取文本文件的流對(duì)象,F(xiàn)ileReader讓創(chuàng)建好的流對(duì)象和指定的文件相關(guān)聯(lián)10             fr=new FileReader("Demo.txt");    11             //第一種讀取方式:read方法,一次讀單個(gè)字符12             int ch=0;13             //read():一次讀一個(gè)字符,而且會(huì)自動(dòng)往下讀。如果讀到流的末尾處就返回-114             while ((ch=fr.read())!=-1)//如果不等于-1就循環(huán)的獲取字符15             {16                 System.out.print((char)ch );//因?yàn)閞ead返回的是int,所以要強(qiáng)轉(zhuǎn)成char類型的17             }18         }19         catch (IOException e)20         {21             System.out.println(e);22         }23         finally24         {25             if(fr!=null)26             try27             {28                 fr.close();29             }30             catch (IOException e)31             {32                 System.out.println("讀取流關(guān)閉失敗");33             }34         }35     }36 }

第二種讀取方式:使用read(char[])方法讀取文本文件數(shù)據(jù)。通過字符數(shù)組進(jìn)行讀取。這種方法比較高效建議用這種方法。

 1 import java.io.*; 2 class FileReaderDemo 3 { 4     public static void main(String[] args)  5     { 6         FileReader fr=null; 7         try 8         { 9             //創(chuàng)建讀取流對(duì)象和指定文件關(guān)聯(lián)。10             fr=new FileReader("Demo.txt");11             //定義一個(gè)變量記錄read的返回值12             int len=0;13             //定義一個(gè)字符數(shù)組,用于存儲(chǔ)讀到字符。一般數(shù)組的長度都是1024的整數(shù)倍。14             char[] buf=new char[1024];15             //該read(char[])返回的是讀到字符個(gè)數(shù)。16             while ((len=fr.read(buf))!=-1)17             {18                 //把char數(shù)組中的數(shù)據(jù)變成字符串打印19                 System.out.println(new String(buf,0,len));20             }21         }22         catch (IOException e)23         {24             System.out.println(e);25         }26         finally27         {28             if(fr!=null)29                 try30                 {31                     fr.close();32                 }33                 catch (IOException e)34                 {35                     System.out.println("讀取流關(guān)閉失敗");36                 }37         }38     }39 }

練習(xí):將D盤的一個(gè)文本文件復(fù)制到E盤。

復(fù)制的原理:其實(shí)就是將D盤下的文件數(shù)據(jù)存儲(chǔ)到E盤的一個(gè)文件中。

步驟:

1,在E盤創(chuàng)建一個(gè)文件。用于存儲(chǔ)D盤文件中的數(shù)據(jù)。

2,定義讀取流和D盤文件關(guān)聯(lián)。

3,通過不斷的讀寫完成數(shù)據(jù)存儲(chǔ)。

4,關(guān)閉資源。

第一種方法:單個(gè)字符不短的讀與寫。

 1 import java.io.*; 2 class CopyDemo  3 { 4     public static void main(String[] args)  5     { 6         FileReader fr=null; 7         FileWriter fw=null; 8         try 9         {10             //1、讀取一個(gè)已有的文本文件,使用字符讀取流和文件相關(guān)聯(lián)11             fr=new FileReader("D://Demo.java");12             //2、創(chuàng)建一個(gè)目的,用于存儲(chǔ)讀到數(shù)據(jù)。13             fw=new FileWriter("E://Demo.java");14             //第一種方法:單個(gè)字符不短的讀與寫15             //3、頻繁的讀寫操作。從D盤讀一個(gè)字符,就往E盤寫一個(gè)字符。16             int ch=0;17             while ((ch=fr.read())!=-1)18             {19                 fw.write(ch);20                 fw.flush();21             }22 23         }24         catch (IOException e)25         {26             System.out.println(e);27         }28         finally29         {30             if(fr!=null)31                 try32                 {33                     //4、關(guān)閉流資源34                     fr.close();35                 }36                 catch (IOException e)37                 {38                     System.out.println("讀取流關(guān)閉失敗");39                 }40             if(fw!=null)41                 try42                 {43                     //4、關(guān)閉流資源44                     fw.close();45                 }46                 catch (IOException e)47                 {48                     System.out.println("輸出流關(guān)閉失敗");49                 }50         }51     }52 }

第二種方法:建立一個(gè)字符數(shù)組緩沖區(qū)。使用read(char[])讀取文本文件數(shù)據(jù)。

 1 import java.io.*; 2 class  CopyDemo 3 { 4     public static void main(String[] args)  5     { 6         FileReader fr=null; 7         FileWriter fw=null; 8         try 9         {10             fr=new FileReader("D://Demo.java");11             fw=new FileWriter("E://Demo.java");12             //創(chuàng)建一個(gè)臨時(shí)容器,用于緩存讀取到的字符13             char[] buf=new char[1024];14             //定義一個(gè)變量記錄讀取到的字符數(shù)(其實(shí)就是數(shù)組里裝的字符個(gè)數(shù))15             int len=0;16             while ((len=fr.read(buf))!=-1)17             {18                 fw.write(buf,0,len);19             }20         }21         catch (IOException e)22         {23             System.out.println(e);24         }25         finally26         {27             if(fr!=null)28                 try29                 {30                     //關(guān)閉流資源31                     fr.close();32                 }33                 catch (IOException e)34                 {35                     System.out.println("讀取流關(guān)閉失敗");36                 }37             if(fw!=null)38                 try39                 {40                     //關(guān)閉流資源41                     fw.close();42                 }43                 catch (IOException e)44                 {45                     System.out.println("輸出流關(guān)閉失敗");46                 }47         }48     }49 }
3、字符流的緩沖區(qū)(BufferedReader、BufferedWriter)

字符流的緩沖區(qū)的出現(xiàn)提高了對(duì)數(shù)據(jù)的讀寫效率。

對(duì)應(yīng)的類:BufferedReader和BufferedWriter。

緩沖區(qū)要結(jié)合流才可以使用。在緩沖區(qū)創(chuàng)建前,要先創(chuàng)建流對(duì)象。即先將流對(duì)象初始化到構(gòu)造函數(shù)中

作用:在流的基礎(chǔ)上對(duì)流的功能進(jìn)行了增強(qiáng)。一般對(duì)字符操作都要加上緩沖區(qū)提高效率。

1 new  BufferedReader(Reader in)//創(chuàng)建一個(gè)使用輸入緩沖區(qū)的緩沖字符輸入流。2 new  BufferedWriter(Writer out)// 創(chuàng)建一個(gè)使用輸出緩沖區(qū)的緩沖字符輸出流。

BufferedReader中特有的行讀取方法:String readLine(),此方法可以實(shí)現(xiàn)對(duì)行的高效讀取。如果讀取到達(dá)流末尾,則返回 null。readLine方法返回的時(shí)候只返回回車符之前的數(shù)據(jù)內(nèi)容,并不返回回車符。其實(shí)readLine方法底層還是調(diào)用了read方法。

BufferedWriter中特有的換行方法:void newline(),此方法可以跨平臺(tái)實(shí)現(xiàn)寫入一個(gè)行分隔符。可以在不同操作系統(tǒng)上調(diào)用,用作數(shù)據(jù)換行

總結(jié):

字符流緩沖區(qū):寫入換行使用BufferedWriter類中的newLine()方法。讀取一行數(shù)據(jù)使用BufferedReader類中的readLine()方法。

只要用到緩沖區(qū),就一定要記得刷新。要不然數(shù)據(jù)還在緩沖區(qū)內(nèi),沒有寫到目的地中去。(關(guān)閉流同樣會(huì)刷新,在循環(huán)的往目的地寫數(shù)據(jù)的時(shí)候,建議寫入一次就刷新一次)。

需求;通過緩沖區(qū)復(fù)制一個(gè).java文件。

 1 import java.io.*; 2 class CopyJavaByBuf  3 { 4     public static void main(String[] args)  5     { 6         BufferedReader bfr=null; 7         BufferedWriter bfw=null; 8         try 9         {10             //為了提高寫入的效率,使用了字符流的緩沖區(qū)11             //只要將需要被提高效率的流對(duì)象作為參數(shù)傳遞給緩沖區(qū)的構(gòu)造函數(shù)即可。 12             bfr=new BufferedReader(new FileReader("D://Demo.java"));13             bfw=new BufferedWriter(new FileWriter("E://Demo.java"));14             String line=null;15             //讀取整行數(shù)據(jù),如果已到達(dá)流末尾,則返回 null 16             while ((line=bfr.readLine())!=null)17             {18                 bfw.write(line);19             //寫入內(nèi)容換行方法:newLine();20                 bfw.newLine();21                 bfw.flush();22             }23         }24         catch (IOException e)25         {26             System.out.println(e);27         }28         finally29         {30             if(bfr!=null)31                 try32                 {33                     bfr.close();34                 }35                 catch (IOException e)36                 {37                     System.out.println("讀取流關(guān)閉失敗");38                 }39             if(bfw!=null)40                 try41                 {42                     bfw.close();43                 }44                 catch (IOException e)45                 {46                     System.out.println("輸出流關(guān)閉失敗");47                 }48         }49     }50 }

需求:模擬一下BufferedReader。自定義一個(gè)類中包含一個(gè)功能和readLine一致的方法。

 1 // 2 import java.io.*; 3 class MyBufferedReader 4 { 5     private Reader r; 6     MyBufferedReader(Reader r){ 7         this.r=r; 8     } 9     //自定義一個(gè)可以一次讀一行數(shù)據(jù)的方法。10     public String myReadLine()throws IOException{11         //定義一個(gè)臨時(shí)容器。原BufferReader封裝的是字符數(shù)組。12         //為了演示方便。定義一個(gè)StringBuilder容器。因?yàn)樽罱K還是要將數(shù)據(jù)變成字符串13         StringBuilder sb=new StringBuilder();14         int ch=0;15         while ((ch=r.read())!=-1)16         {17             if(ch=='/r')18                 continue;19             if(ch=='/n')20                 return sb.toString();21             else22                 sb.append((char)ch);23         }24         if(sb.length()!=0)//如果sb中還有數(shù)據(jù)的話返回?cái)?shù)據(jù)25             return sb.toString();26         return null;//如果已經(jīng)讀到流的末尾了返回null。BufferedReader中的readLine()返回的也是null.27     }28     //定義一個(gè)自己的關(guān)閉流資源的方法29     public void myClose()throws IOException{30         r.close();//字符流緩沖區(qū)的close方法其實(shí)就是調(diào)用了Reader方法中的close的方法,31                     //所以只需要關(guān)閉字符流緩沖區(qū)的流對(duì)象即可。32     }33 34 }35 class MyBufferedReaderDemo36 {37     public static void main(String[] args)throws IOException38     {39         MyBufferedReader bfr=new MyBufferedReader(new FileReader("D://Demo.java"));40         String line=null;41         while ((line=bfr.myReadLine())!=null)42         {43             System.out.println(line);44         }45         bfr.myClose();46     }47 }
4、LineNumberReader

跟蹤行號(hào)的緩沖字符輸入流。此類定義了方法 setLineNumber(int) 和 getLineNumber(),它們可分別用于設(shè)置和獲取當(dāng)前行號(hào)。

(1)、LineNumberReader常用方法

1  構(gòu)造方法:new LineNumberReader(Reader in);//使用默認(rèn)輸入緩沖區(qū)的大小創(chuàng)建新的行編號(hào) reader。2 int  getLineNumber();//獲取行號(hào)3 void  setLineNumber();//設(shè)置行號(hào)4 String  readLine();//讀取整行數(shù)據(jù)

既然LineNumberReader繼承了BufferedReader為何還要復(fù)寫readLine()呢?

因?yàn)長ineNumberReader的readLine()方法中加入了行號(hào)的操作的,所以要復(fù)寫B(tài)ufferedReader中的readLine方法。

(2)、需求:模擬一個(gè)帶行號(hào)的緩沖區(qū)對(duì)象,就是自定義一個(gè)LineNumberReader。

 1 import java.io.*; 2 class MyLineNumberReader  3 { 4     private Reader r; 5     private int lineNumber; 6     MyLineNumberReader(Reader r){ 7         this.r=r; 8     } 9     public void setLineNumber(int lineNumber){//設(shè)置行號(hào)10         this.lineNumber=lineNumber;11     }12     public int getLineNumber(){//獲取行號(hào)13         return lineNumber;14     }15     public String myReadLine()throws IOException{16         lineNumber++;//每調(diào)用一次myReadLine行號(hào)都自增1。17         StringBuilder sb=new StringBuilder();18         int ch=0;19         while((ch=r.read())!=-1){20             if(ch=='/r')21                 continue;22             if(ch=='/n')23                 return sb.toString();24             sb.append((char)ch);25         }26         if(sb.length()!=0)27             return sb.toString();28         return null;29     }30     public void myClose()throws IOException{31         r.close();32     }33 }34 class MyLineNumberReaderDemo35 {36     public static void main(String[] args) throws IOException37     {38         MyLineNumberReader mlnr=new MyLineNumberReader(new FileReader("D://Demo.java"));39         mlnr.setLineNumber(100);40         String line=null;41         while ((line=mlnr.myReadLine())!=null)42         {43             System.out.println(mlnr.getLineNumber()+":"+line);44         }45         mlnr.myClose();46     }47 }
5、裝飾設(shè)計(jì)模式

MyReader//專門用于讀取數(shù)據(jù)的類。

|--MyTextReader

|--MyBufferTextReader

|--MyMediaReader

|--MyBufferMediaReader

|--MyDataReader

|--MyBufferDataReader

class MyBufferReader

{

MyBufferReader(MyTextReader text){}

MyBufferReader(MyMediaReader media){}

}

上面這個(gè)類擴(kuò)展性很差。

找到其參數(shù)的共同類型。通過多態(tài)的形式。可以提高擴(kuò)展性。

class MyBufferReader extends MyReader

{

private MyReader r;

MyBufferReader(MyReader r) {}

}

MyReader//專門用于讀取數(shù)據(jù)的類。

|--MyTextReader  

  |--MyMediaReader

|--MyDataReader

|--MyBufferReader

  以前是通過繼承將每一個(gè)子類都具備緩沖功能。那么繼承體系會(huì)復(fù)雜,并不利于擴(kuò)展。現(xiàn)在優(yōu)化思想。單獨(dú)描述一下緩沖內(nèi)容。將需要被緩沖的對(duì)象。傳遞進(jìn)來。也就是,誰需要被緩沖,誰就作為參數(shù)傳遞給緩沖區(qū)。這樣繼承體系就變得很簡單。優(yōu)化了體系結(jié)構(gòu)。

  裝飾模式比繼承要靈活。避免了繼承體系臃腫。而且降低了類于類之間的關(guān)系。裝飾類因?yàn)樵鰪?qiáng)已有對(duì)象,具備的功能和已有的是相同的,只不過提供了更強(qiáng)功能。所以裝飾類和被裝飾類通常是都屬于一個(gè)體系中的。裝飾和繼承都能實(shí)現(xiàn)一樣的特點(diǎn):進(jìn)行功能的擴(kuò)展增強(qiáng)。有什么區(qū)別呢?

首先有一個(gè)繼承體系:

Writer

|--TextWriter:用于操作文本

|--MediaWriter:用于操作媒體

如果想要對(duì)操作的動(dòng)作進(jìn)行效率的提高,按照面向?qū)ο螅梢酝ㄟ^繼承的方式對(duì)具體的對(duì)象進(jìn)行功能的擴(kuò)展,那么就需要加入緩沖技術(shù)。

Writer

|--TextWriter:用于操作文本

|--BufferTextWriter:加入了緩沖技術(shù)的操作文本的對(duì)象

|--MediaWriter:用于操作媒體

  |--BufferMediaWriter:加入了緩沖技術(shù)的操作媒體的對(duì)象 以上方式并不理想,如果這個(gè)體系需要再進(jìn)行功能擴(kuò)展,又多了更多流對(duì)象。這樣就會(huì)發(fā)現(xiàn)只為提高功能,導(dǎo)致繼承體系越來越臃腫,不夠靈活。

重新思考問題:既然加入的都是同一種技術(shù)--緩沖。前一種是讓緩沖和自己的流對(duì)象相結(jié)合。可不可以將緩沖進(jìn)行單獨(dú)的封裝,哪個(gè)對(duì)象需要緩沖就將哪個(gè)對(duì)象和緩沖關(guān)聯(lián)。

class Buffer {

Buffer(TextWriter w){}

Buffer(MediaWriter w){}

}

簡化為:

class BufferedWriter extends Writer{

BufferedWriter(Writer w){}

}

Writer

|--TextWriter:用于操作文本

|--MediaWriter:用于操作媒體

|--BufferedWriter:用于提高效率

可見:裝飾比繼承靈活。

特點(diǎn):裝飾類和被裝飾類都必須所屬同一個(gè)接口或者父類。

三、IO流常用基類----字節(jié)流

1、基本操作與字符流類相同。但它不僅可以操作字符,還可以操作其他媒體文件。

2、由于媒體文件數(shù)據(jù)中都是以字節(jié)存儲(chǔ)的,所以,字節(jié)流對(duì)象可直接對(duì)媒體文件的數(shù)據(jù)寫入到文件中,而可以不用再進(jìn)行刷流動(dòng)作。

1、OutputStream 抽象類

此抽象類是表示輸出字節(jié)流的所有類的超類。輸出流接受輸出字節(jié)并將這些字節(jié)發(fā)送到某個(gè)接收器。

(1)、OutputStream常用方法

1 void  close();//關(guān)閉輸出流2 void  flush();//刷新輸出流并強(qiáng)制寫出所有緩沖的輸出字節(jié)3 void  write(byte[] buf);//寫出一個(gè)byte型數(shù)組4 void  write(byte[] buf,int off,int len);//將指定 byte 數(shù)組從偏移量 off 開始, len 個(gè)字節(jié)寫入此輸出流5 void  write(int b);//寫出一個(gè)字節(jié)

(2)、FileOutputStream類

因?yàn)镺utputStream是抽象的,無法創(chuàng)建對(duì)象。所以我們找到一個(gè)專門用于操作文件的OutputStream子類對(duì)象:FileOutputStream。后綴名是父類名,前綴名是該流對(duì)象的功能。該對(duì)象可以直接操作文件。所以可以直接用OutputStream中的方法操作文件。但是這個(gè)對(duì)象可以創(chuàng)建對(duì)象,我們用它的構(gòu)造函數(shù)。

1 new  FileOutputStream(String name);//創(chuàng)建一個(gè)向具有指定名稱的文件中寫入數(shù)據(jù)的輸出文件流。2 new  FileOutputStream(String name,boolean append);//創(chuàng)建一個(gè)向具有指定 name 的文件中寫入數(shù)據(jù)的輸出文件流。該構(gòu)造函數(shù)具有續(xù)寫的功能。3 new  FileOutputStream(File flie);//創(chuàng)建一個(gè)向指定 File 對(duì)象表示的文件中寫入數(shù)據(jù)的文件輸出流。4 new  FileOutputStream(File file,boolean append);//創(chuàng)建一個(gè)向指定 File 對(duì)象表示的文件中寫入數(shù)據(jù)的文件輸出流。

代碼演示:

 1 import java.io.*; 2 class FileOutputStreamDemo  3 { 4     public static void main(String[] args)throws IOException  5     { 6         //1、創(chuàng)建字節(jié)輸出流對(duì)象,用于操作文件 7         FileOutputStream fos=new FileOutputStream("黑馬.txt"); 8         //2、寫數(shù)據(jù),直接寫入到了目的地中 9         fos.write("我愛黑馬".getBytes());10         //OutputStream 可以不用flush。因?yàn)樽止?jié)流操作的是字節(jié),是數(shù)據(jù)的最小單位。可以直接輸出而不用刷新。11         //3、關(guān)閉資源動(dòng)作要完成12         fos.close();13     }14 }
2、InputStream 抽象類

此抽象類是表示字節(jié)輸入流的所有類的超類。

(1)、 InputStream中的常用方法

1 int available();//返回輸入流讀取的字節(jié)數(shù)2 void close();//關(guān)閉此輸入流3 abstract int   read();//一個(gè)一個(gè)字符的讀取數(shù)據(jù)4 int  read(byte[] b);//從輸入流中讀取一定數(shù)量的字,并將其存儲(chǔ)在緩沖區(qū)數(shù)組 b 中。5 int  read(byte[] b,int off,int len);//將輸入流中最多 len 個(gè)數(shù)據(jù)字節(jié)讀入 byte 數(shù)組。

(2)、FileInputStream類

因?yàn)镮nputStream是抽象的,無法創(chuàng)建對(duì)象。所以我們找到一個(gè)專門用于操作文件的InputStream子類對(duì)象:FileInputStream。后綴名是父類名,前綴名是該流對(duì)象的功能。該對(duì)象可以直接操作文件。所以可以直接用InputStream中的方法操作文件。但是這個(gè)對(duì)象可以創(chuàng)建對(duì)象,我們用它的構(gòu)造函數(shù)。

1 new InputStream(String name);//創(chuàng)建一個(gè)向具有指定名稱的文件中寫入數(shù)據(jù)的讀取文件流。2 new InputStream(File file);//創(chuàng)建一個(gè)向指定 File 對(duì)象表示的文件中寫入數(shù)據(jù)的文件讀取流。

代碼演示:

 1 import java.io.*; 2 class FileInputStreamDemo  3 { 4     public static void main(String[] args) throws IOException 5     { 6          7 //        read_1(); 8 //        read_2(); 9         read_3();10     }11     //單個(gè)字節(jié)的讀取12     public static void read_1()throws IOException{13         //創(chuàng)建一個(gè)讀取流對(duì)象,和指定文件關(guān)聯(lián)14         FileInputStream fis=new FileInputStream("Demo.txt");15         int ch=0;16         while ((ch=fis.read())!=-1)17         {18             System.out.print((char)ch);19         }20         fis.close();21     }22     //創(chuàng)建緩沖區(qū),提高讀取效率23     public static void read_2()throws IOException{24         FileInputStream fis=new FileInputStream("Demo.txt");25         int len=0;26         //建立數(shù)組把數(shù)據(jù)存儲(chǔ)到數(shù)組緩沖區(qū)中27         byte[] buf=new byte[1024];28         while ((len=fis.read(buf))!=-1)29         {30             System.out.print(new String(buf,0,len));31         }32         fis.close();33     }34     //創(chuàng)建一個(gè)剛剛好的數(shù)組35     public static void read_3()throws IOException{36         FileInputStream fis=new FileInputStream("Demo.txt");37         //打印字符字節(jié)大小,文件太大,可能內(nèi)存溢出。不建議用38         byte[] buf=new byte[fis.available()];39         int len=fis.read(buf);40         System.out.println(new String(buf,0,len));41     fis.close();42     }43 }

需求:復(fù)制一個(gè)圖片

思路:

1,用字節(jié)讀取流對(duì)象和圖片關(guān)聯(lián)。

2,用字節(jié)寫入流對(duì)象創(chuàng)建一個(gè)圖片文件。用于存儲(chǔ)獲取到的圖片數(shù)據(jù)。

3,通過循環(huán)讀寫,完成數(shù)據(jù)的存儲(chǔ)。

4,關(guān)閉資源。

 1 import java.io.*; 2 class  CopyPicDemo 3 { 4     public static void main(String[] args)throws IOException  5     { 6         copy_1(); 7         copy_2(); 8     } 9     //一個(gè)字節(jié)一個(gè)字節(jié)的讀寫10     public static void copy_1()throws IOException{11         FileInputStream fis=new FileInputStream("D://1.jpg");12         FileOutputStream fos=new FileOutputStream("E://1.jpg");        13         int ch=0;14         while ((ch=fis.read())!=-1)15         {16             fos.write(ch);17         }18         fis.close();19         fos.close();20     }21     //定義數(shù)組緩沖區(qū)高效讀寫22     public static void copy_2()throws IOException{23         FileInputStream fis=new FileInputStream("D://1.jpg");24         FileOutputStream fos=new FileOutputStream("E://1.jpg");    25         byte[] buf=new byte[1024];26         int len=0;27         while ((len=fis.read(buf))!=-1)28         {29             fos.write(buf,0,len);30         }31         fos.close();32         fis.close();33     }34 }

需求:自定義一個(gè)字節(jié)流緩沖區(qū)復(fù)制mp3文件。

 1 import java.io.*; 2 class MyBufferedInputStream 3 { 4     private InputStream in; 5     private byte[] buf=new byte[1024]; 6     private int count=0,pos=0;//初始化個(gè)數(shù),和數(shù)組指針 7     MyBufferedInputStream(InputStream in){ 8         this.in=in; 9     }10     public int myRead()throws IOException{11         //如果緩沖區(qū)中沒有數(shù)據(jù)count==0,那么就從硬盤上取一批數(shù)據(jù)到數(shù)組緩沖區(qū)中,12         //用count記錄住數(shù)組中的數(shù)據(jù)個(gè)數(shù),每次獲取數(shù)據(jù)到緩沖區(qū)后,角標(biāo)歸零13         if(count==0){14             count=in.read(buf);15             pos=0;                16         }17         //如果count<0的時(shí)候表示數(shù)組中沒有數(shù)據(jù)了,返回-118         if(count<0){19             return -1;20         }21         else{//表示數(shù)組中有數(shù)據(jù),就從數(shù)組中一個(gè)一個(gè)的取數(shù)據(jù)22             byte by=buf[pos];23             pos++;24             count--;25             return by&255;//返回的byte類型提升為int類型,字節(jié)數(shù)增加,且高24位被補(bǔ)1,原字節(jié)數(shù)據(jù)改變。  26                           //通過與上255,主動(dòng)將byte類型提升為int類型,將高24位補(bǔ)0,原字節(jié)數(shù)據(jù)不變。  27                           //而在輸出字節(jié)流寫入數(shù)據(jù)時(shí),只寫該int類型數(shù)據(jù)的最低8位。  28         }        29     }30     public void myClose()throws IOException{31         in.close();32     }33 }34 class CopyMp3Demo 35 {36     public static void main(String[] args) throws IOException37     {38         long start=System.currentTimeMillis();39         runCode();40         long end=System.currentTimeMillis();41         System.out.println("毫秒:"+(end-start));42     }43     public static void runCode()throws IOException{44         MyBufferedInputStream fis=new MyBufferedInputStream(new FileInputStream("D://年輪.mp3"));45         FileOutputStream fos=new FileOutputStream("E://年輪.mp3");46         int ch=0;        47         while ((ch=fis.myRead())!=-1)48         {49             fos.write(ch);50         }51         fis.myClose();52         fos.close();53     }54 }

結(jié)論:

字節(jié)流的讀一個(gè)字節(jié)的read方法為什么返回值類型不是byte,而是int?

  因?yàn)橛锌赡軙?huì)讀到連續(xù)8個(gè)二進(jìn)制1的情況,8個(gè)二進(jìn)制1對(duì)應(yīng)的十進(jìn)制是-1。那么就會(huì)數(shù)據(jù)還沒有讀完,就結(jié)束的情況。因?yàn)槲覀兣袛嘧x取結(jié)束是通過結(jié)尾標(biāo)記-1來確定的。所以,為了避免這種情況將讀到的字節(jié)進(jìn)行int類型的提升。并在保留原字節(jié)數(shù)據(jù)的情況前面了補(bǔ)了24個(gè)0,變成了int類型的數(shù)值。而在寫入數(shù)據(jù)時(shí),只寫該int類型數(shù)據(jù)的最低8位。所以:read方法在提升,而write方法在降低。這樣就不會(huì)導(dǎo)致數(shù)據(jù)的不一致。

四、轉(zhuǎn)換流----InputStreamReader、OutputStreamWriter

繼承體系

Reader

  |--InputStreamReader

    |--FileReader

Writer

  |--OuputStreamWriter

    |--FileWriter

轉(zhuǎn)換流最強(qiáng)大的地方就是可以指定編碼表。

(1)、InputStreamReader 字節(jié)流通向字符流的橋梁。解碼。

它使用指定的 charset 讀取字節(jié)并將其解碼為字符。它使用的字符集可以由名稱指定或顯式給定,或者可以接受平臺(tái)默認(rèn)的字符集。

構(gòu)造方法:

1 new InputStreamReader(InputStream in);//創(chuàng)建一個(gè)使用默認(rèn)字符集的 InputStreamReader2 new InputStreamReader(InputStream in,Charset cs);//創(chuàng)建使用給定字符集的 InputStreamReader3 new InputStreamReader(InputStream in,CharsetDecoder dec);//創(chuàng)建使用給定字符集解碼器的 InputStreamReader4 new InputStreamReader(InputStream in,String charsetName);//創(chuàng)建使用指定字符集的 InputStreamReader

(2)、OutputStreamWriter 字符流通向字節(jié)流的橋梁。編碼。

可使用指定的 charset 將要寫入流中的字符編碼成字節(jié)。它使用的字符集可以由名稱指定或顯式給定,否則將接受平臺(tái)默認(rèn)的字符集。

1 new OutputStreamWriter(OutputStream out);//創(chuàng)建使用默認(rèn)字符編碼的 OutputStreamWriter2 new OutputStreamWriter(OutputStream out,Charset cs);//創(chuàng)建使用給定字符集的 OutputStreamWriter 3 new OutputStreamWriter(OutputStream out, CharsetEncoder enc);//創(chuàng)建使用給定字符集編碼器的 OutputStreamWriter4 new OutputStreamWriter(OutputStream out, String charsetName));//創(chuàng)建使用指定字符集的 OutputStreamWriter

使用字節(jié)流讀取一個(gè)中文字符需要讀取兩次,因?yàn)橐粋€(gè)中文字符由兩個(gè)字節(jié)組成,而使用字符流只需讀取一次。System.out的類型是PrintStream,屬于OutputStream類別。

什么時(shí)候使用轉(zhuǎn)換流呢?

1、源或者目的對(duì)應(yīng)的設(shè)備是字節(jié)流,但是操作的卻是文本數(shù)據(jù),可以使用轉(zhuǎn)換作為橋梁,提高對(duì)文本操作的便捷。  

 2、一旦操作文本涉及到具體的指定編碼表時(shí),必須使用轉(zhuǎn)換流。

(3)、讀取鍵盤錄入

鍵盤本身就是一個(gè)標(biāo)準(zhǔn)的輸入設(shè)備。對(duì)于java而言,對(duì)于這種輸入設(shè)備都有對(duì)應(yīng)的對(duì)象。默認(rèn)的輸入和輸出系統(tǒng)不需要關(guān),它會(huì)隨著系統(tǒng)的結(jié)束而消失。

System.in:對(duì)應(yīng)的標(biāo)準(zhǔn)輸入設(shè)備,鍵盤。

Ssytem.out:對(duì)應(yīng)的是標(biāo)準(zhǔn)的輸出設(shè)備,控制臺(tái)。

System.in的類型是InputStream。

System.out的類型是PrintStream是OutputStream的子類。

需求:獲取用戶鍵盤錄入的數(shù)據(jù)并將數(shù)據(jù)變成大寫顯示在控制臺(tái)上,如果用戶輸入的是over,結(jié)束鍵盤錄入。

思路:

1. 因?yàn)殒I盤錄入只讀取一個(gè)字節(jié),要判斷是否是over,需要將讀取到的字節(jié)拼成字符串。

2. 那就需要一個(gè)容器:StringBuilder。

3. 在用戶回車之前將錄入的數(shù)據(jù)變成字符串判斷即可。

 1 import java.io.*; 2 class  ReadKey 3 { 4     public static void main(String[] args) throws IOException 5     { 6         //獲取鍵盤讀取流,System.in 是InputStream的子類 7         InputStream in=System.in; 8         //創(chuàng)建容器 9         StringBuilder sb=new StringBuilder();10         //定義變量記錄讀取到的字節(jié),并循環(huán)獲取11         int ch=0;12         while ((ch=in.read())!=-1)13         {14             //如果是/r,繼續(xù)循環(huán)15             if(ch=='/r')16                 continue;17             //如果是/n,把緩沖區(qū)的數(shù)據(jù)變成字符串18             if(ch=='/n'){19                 String s=sb.toString();20                 if("over".equals(s))//如果變成的字符串正好是over,就停止循環(huán)21                     break;22                 System.out.println(s.toUpperCase());23                 sb.delete(0,sb.length());//清空緩沖區(qū)的數(shù)據(jù)24             }25             else26                 sb.append((char)ch);//如果以上的情況都不是,則將讀取到的字節(jié)存儲(chǔ)到StringBuilder中27 28         }29     }30 }

通過剛才的鍵盤錄入一行數(shù)據(jù)并打印其大寫,發(fā)現(xiàn)其實(shí)就是讀一行數(shù)據(jù)的原理。也就是readLine方法。能不能直接使用readLine方法來完成鍵盤錄入的一行數(shù)據(jù)的讀取呢?

readLine方法是字符流BufferedReader類中的方法。而鍵盤錄入的read方法是字節(jié)流InputStream的方法。那么能不能將字節(jié)流轉(zhuǎn)成字符流在使用字符流緩沖去的readLine方法呢?

這時(shí)候我們查看API發(fā)現(xiàn)Reader類中有一個(gè)字節(jié)通向字符的橋梁:InputStreamReader,而Writer類中有一個(gè)字符通向字節(jié)的橋梁:OutputStreamWriter。

這兩個(gè)轉(zhuǎn)換流可以將字節(jié)流轉(zhuǎn)換成字符流,這樣我們就可以用字節(jié)流緩沖區(qū)的readLine方法一行一行的讀取數(shù)據(jù)比較方便。

 1 import java.io.*; 2 class ReadIn{ 3     public static void main(String[] args)throws IOException( 4         //獲取鍵盤錄入對(duì)象 5         InputStream in=System.in; 6  7         //將字節(jié)流轉(zhuǎn)成字符流,用轉(zhuǎn)換流InputStreamReader 8         InputStreamReader isr=new InputStreamReader(in); 9 10         //為了提高效率,將字符串進(jìn)行緩沖區(qū)技術(shù)高效操作。    11         BufferedReader bfr=new BufferedReader(isr);12 13         //字節(jié)輸出流14         OutputStream out=System.out;1516         //將字符轉(zhuǎn)成字節(jié)的橋梁17        OutputStreamWriter osw=new OutputStreamWriter(out);18         //對(duì)字符流進(jìn)行高效裝飾,緩沖區(qū)19         BufferedWriter bfw=new BufferedWriter(osw);20         String line=null;       21         while((line=bfr.readLine)!=null){22             if(“over”.equals(line))23                 break;24             bfw.write(line.toUpperCase());25             bfw.newLine();26             bfw.flush();27         }    28 }                                             

上面的代碼可以簡寫成下面的代碼:

 1 import java.io.*; 2 class ReadKey  3 { 4     public static void main(String[] args) throws IOException 5     { 6         //讀取鍵盤錄入最常見的方法 7         BufferedReader in=new BufferedReader(new InputStreamReader(System.in)); 8         BufferedWriter out=new BufferedWriter(new OutputStreamWriter(System.out)); 9         String line=null;10         while ((line=in.readLine())!=null)11         {12             if("over".equals(line))13                 break;14             out.write(line.toUpperCase());15             out.newLine();16             out.flush();17         }18         in.close();19         out.close();20     }21 }

獲取鍵盤錄入數(shù)據(jù),然后將數(shù)據(jù)流向顯示器,那么顯示器就是目的地。 通過System類的setIn(InputStream in),setOut(PrintStream out)方法可以對(duì)默認(rèn)設(shè)備進(jìn)行改變。

System.setIn(new FileInputStream(“1.txt”));//將源改成文件1.txt。

System.setOut(new PrintStream(“2.txt”));//將目的改成文件2.txt

因?yàn)槭亲止?jié)流處理的是文本數(shù)據(jù),可以轉(zhuǎn)換成字符流,操作更方便。

讀取鍵盤錄入最常見的方法:BufferedReader in=new BufferedReader(new InputStreamReader(System.in));

擴(kuò)展:鍵盤錄入常見的三種操作

1 /方法一:從控制臺(tái)接收一個(gè)字符,然后將其打印出來2 import java.io.*;3 public static void main(String[] args)throws IOException{4     System.out.print(“請(qǐng)輸入一個(gè)字符”);5     char ch=(char)System.in.read();6     System.out.println(“你輸入的字符是:”+ch);7 }

雖然上面的方式實(shí)現(xiàn)了從鍵盤獲取輸入的字符,但是System.out.read()只能針對(duì)一個(gè)字符的獲取,同時(shí),獲取進(jìn)來的變量的類型只能是char,當(dāng)我們輸入一個(gè)數(shù)字,希望得到的也是一個(gè)整型變量的時(shí)候,我們還得修改其中的變量類型,這樣就顯得比較麻煩。

1 //方法二:從控制臺(tái)接收一個(gè)字符串,然后將其打印出來。用到BufferedReader類和InputStreamReader類。2 import java.io.*;3 public static void main(String[] args)throws IOException{4     BufferedReder bfr=new BufferedReader(new InputStreamReader(System.in));5     String str=null;6     System.out.println(“輸入你的數(shù)據(jù):”);7     str.bfr.readLine();8     System.out.println(“輸入的值是:”+str);9 }

這種方法可以獲取我們輸入的字符串?dāng)?shù)據(jù)。

 1 //第三種方法:這種方法我認(rèn)為是最簡單,最強(qiáng)大的,就是用Scanner類。 2 import java.util.Scanner; 3 public static void main(String[] args){ 4     Scanner sc=new Scanner(System.in); 5     Systm.out.println(“請(qǐng)輸入你的名字”); 6     String name=sc.nextLine(); 7     System.out.println(“請(qǐng)輸入你的年齡”); 8     int age=sc.nextInt(); 9     System.out.println(“請(qǐng)輸入你的工資”);10     double salary=sc.nextDouble();11     System.out.println(“你的信息如下:”);12     System.out.println("姓名:"+name+"/n"+"年齡:"+age+"/n"+"工資:"+salary);13 }

這段代碼已經(jīng)表明,Scanner類不管是對(duì)于字符串還是整型數(shù)據(jù)或者float類型的變量,只需做一點(diǎn)小小的改變,就能夠?qū)崿F(xiàn)功能!無疑他是最強(qiáng)大的!

五、流操作的規(guī)律

之所以要弄清楚這個(gè)規(guī)律,是因?yàn)榱鲗?duì)象太多,開發(fā)時(shí)不知道用哪個(gè)對(duì)象合適。想要知道對(duì)象的開發(fā)時(shí)用到哪些對(duì)象,只要通過四個(gè)明確即可。

1、流操作規(guī)律

(1)、明確源和目的

源:輸入流。InputStream Reader

目的:輸出流。OutputStream Writer

(2)、操作的數(shù)據(jù)是否是純文本

源:是純文本:字符流Reader

不是:字節(jié)流 InputStream

目的:是純文本:字符流Writer

不是:字節(jié)流: OutputStream

(3)、當(dāng)體系明確后,在明確要使用哪個(gè)具體的對(duì)象。

通過設(shè)備可以來進(jìn)行區(qū)分:

  源設(shè)備:硬盤(File)、鍵盤(System.in)、內(nèi)存(數(shù)組流)、網(wǎng)絡(luò)(Socket流)。

  目的設(shè)備:硬盤(File)、控制臺(tái)(System.out)、內(nèi)存(數(shù)組流)、網(wǎng)絡(luò)(Socket流)。

(4)、是否西藥其他額外的功能

是否需要高效(緩沖區(qū)):是,就加上buffered。

需求1:復(fù)制一個(gè)文本文件

(1)、明確源和目的

  源:InputStream Reader

  目的:OutputStream Writer

(2)、是否是純文本

  是:源:Reader

  目的:Writer

(3)、明確操作的設(shè)備

  源:硬盤:File

  目的:硬盤:File

1 FileReader fr=new FileReader(“a.txt”);2 3  FileWriter fw=new FileWriter(“b.txt”);

(4)、是否需要高效

  是

1  BufferedReader bfr=new BufferedReader(fr);2 3 BufferedWriter bfw=new BufferedWriter(fw);

需求2:讀取鍵盤錄入信息,并寫入到一個(gè)文件中

(1)、明確源和目的

  源:InputStream Reader

  目的:OutputStream Writer

(2)、明確是否是純文本

  是:源:Reader

  目的:Writer

(3)、明確具體設(shè)備

  源:鍵盤:System.in

  目的:文件:File

System.in對(duì)應(yīng)的不是字節(jié)流嗎?為了操作鍵盤的文本數(shù)據(jù)方便。轉(zhuǎn)成字符流按照字符串操作是最方便的。所以既然明確了Reader,那么就將System.in轉(zhuǎn)換成Reader。

用了Reader體系中轉(zhuǎn)換流,InputStreamReader。

1 InputStream is=(new InputStreamReader(System.in);2 3 FileWriter fw=new FileWriter(“c.txt”);

(4)、需要高效嗎?

1 BufferedReader bfr=new BufferedReader(is);2 3 BufferedWriter bfw=new BufferedWriter(fw);

需求3:將一個(gè)文本文件數(shù)據(jù)顯示在控制臺(tái)上

(1)、明確源和目的

  源:InputStream Reader

  目的:OutputStream Writer

(2)、是否是純文本

  是:源:Reader

  目的:Writer

(3)、明確設(shè)備

  源:文件:File

  目的:控制臺(tái):System.out

1 FileReader fr=new FileReader(“a.txt”);2 3 OutputStreamWriter osw=new OutputStreamWriter(System.out);

(4)、是否需要高效

1 BufferedReader bfr=new BufferedReader(fr);2 3 BufferedWriter bfw=new
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 阿拉善右旗| 和平区| 襄汾县| 疏勒县| 那坡县| 沂源县| 五峰| 潜山县| 屯昌县| 民县| 永修县| 黄骅市| 屯门区| 江都市| 米脂县| 察雅县| 鄢陵县| 宜城市| 易门县| 临猗县| 江达县| 湛江市| 天峨县| 垦利县| 隆化县| 曲沃县| 子洲县| 德江县| 枝江市| 婺源县| 大化| 三明市| 宁南县| 门头沟区| 舒城县| 禹州市| 宁德市| 宝山区| 赞皇县| 文化| 鄂温|