------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
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注