黑馬程序員_day22_IO流

----------- android培訓java培訓、java學習型技術博客、期待與您交流! ------------

IO流用來處理設備之間的數據傳輸

Java對數據的操作是通過流的方式

Java用於操作流的對象都在IO包中

流按操作數據分爲兩種:字節流和字符流

流按流向分爲:輸入流、輸出流

一、字符流的由來:

以前處理數據都是字節數據,使用字節流技術就可以完成了。

因爲後期編碼表的不斷出現,識別某一文字的碼錶不唯一。比如中文,GBKunicode都可以識別。

就出出現了編碼問題。

中文字節數據 gbk --> 流處理--->gbk解析可以了。 

後期:容器出現這樣的問題:

中文字節數據gbk --> 流處理 unicode來處理-->數據錯誤。

爲了處理文字數據,就需要通過 字節流技術+編碼表 相結合來完成。注意:只有文字是這樣的,因爲文字涉及編碼問題。

其他數據比如dvd mp3 圖片等是不涉及這個問題的。

雖然字節流+編碼表可以解決文字數據處理問題,但是較爲麻煩。

爲了便於使用,將字節流和編碼表進行了封裝,就出現了便於文字操作的流技術:字符流。

其實字符流就是:字節流+編碼表。

二、IO的體系

字節流兩個基類:

InputStream(字節輸入流)  OutputStream(字節輸出流)

字符流兩個基類:

Reader(字符輸入流) Writer(字符輸出流)

學習io流體系:看頂層(父類共性功能),用底層(子類具體對象)

該體系的一個好處就是:

每個子類的後綴名都是所屬體系的父類的名稱,很容易區分所屬的體系。而且每一個子類前綴名都是該子類對象的功能體現。

三、練習

1、需求:將一個段文字數據寫入到硬盤上.

思路:

1,一段文字就是字符串數據。

2,寫到硬盤上,字符串數據在內存中,是將內存中的數據搞 到硬盤上,這就涉及到了設備之間的數據處理。就要用到IO 技術。從內存到硬盤,應該是輸出流。

3,對於文字而言,io中提供了便捷的操作,比如字符流。

4,結合兩者,需要輸出流,需要字符流,可使用字符輸出流。 Writer

5,具體用哪個子類對象呢?硬盤上用於存儲數據的體現:文 件。希望可以在Writer體系中知道可以操作文件的Writer對象。 

找到了具體的對象FileWriter.

1,通過FileWriter創建流對象。構造時,必須明確寫入數據需要存儲的位置。 

該對象一創建,目的文件就會被創建。

如果該文件已經存在,會被覆蓋。 

做了什麼事呢?在堆內存中創建一個對象。同時調用了系統的資源。

FileWriter fw = new FileWriter("demo.txt");

當前目錄下創建demo.txt文件。

2,使用字符輸出流對象將字符串進行寫入。調用寫入方法。

數據沒有直接寫入到目的文件中,而是寫入到了臨時緩衝中。

fw.write("abcdef");

3,怎麼把數據弄到文件中呢?Writer類中有一個flush()方法。刷新緩衝區,將緩衝的數據立即寫入到目標中。

fw.flush();

4,關閉此流,關閉資源。在關閉之前,先刷一次緩衝,將數據都寫入到目的中。

fw.close();

fw.write("XIXI");//Stream closed流已關閉。不能再寫

flush()close()有什麼區別?

 flush():僅將緩衝中的數據刷新到目的地。流對象可以繼續使用。可以使用多次。

 close():將緩衝中的數據刷到目的地後,直接關閉流資源,流無法繼續使用。只能使用一次。

close()方法當中其實在關閉之前都會調用一次flush();

2、需求:想要來個續寫。

這個對象創建是不行的,因爲該構造一創建,就覆蓋了已有的文件。 

可以使用另一個構造函數,加入一個boolean參數,爲true,就可以實現續寫。

3、需求:想要將數據分行寫入。

window中的特有軟件比如notepad。只識別window中的特有換行 \r\n.

爲了在不同系統平臺下換行。可使用System類獲取當前系統信息。

續寫和換行的代碼:

private static final String LINE_SPARATOR = System.getProperty("line.separator");

public static void main(String[] args) throws IOException {

FileWriter fw = new FileWriter("tempfile\\demo2.txt",true);

fw.write("xi"+LINE_SPARATOR+"xi");

fw.close();

}

四、IO異常的處理規範

IO異常的處理規範: 創建流對象。 在try外創建流對象的引用。 在try內對流對象進行初始化。

FileWriter fw = null;

try {

fw = new FileWriter("k:\\demo3.txt");

fw.write("abcde");

fw.flush();

} catch (IOException e) {

System.out.println(e.toString());

} finally {

if (fw != null)健壯性判斷否則會出現空指針異常。注意如果 需關閉多個流,則需一個一個的判斷

try {

fw.close();

} catch (IOException e) {

  相關的代碼處理。比如說,將關閉失敗的信息記錄到日誌 文件中。

throw new RuntimeException("關閉失敗");

}

}

五、FileReader 讀取字符

public static void main(String[] args) throws IOException {

使用FileReader在構造時明確被讀取的文件。

通過FileReader和指定的文件相關聯。

FileReader fr = new FileReader("tempfile\\demo.txt");

調用字符讀取流對象的read方法。對關聯的文件進行讀取。 

read():一次讀取一個字符。並返回該字符的對應的數字。

讀取到什麼字符,就返回什麼字符,讀到結尾就返回-1.-1來標示結束了。

// int ch = fr.read();

// System.out.println("ch="+ch);

// int ch1 = fr.read();

// System.out.println("ch1="+ch1);

// int ch2 = fr.read();

// System.out.println("ch2="+ch2);

// int ch3 = fr.read();

// System.out.println("ch3="+ch3);

//代碼使用循環解決

int ch = 0;

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

System.out.println((char)ch);

}

//關閉資源。

fr.close();

}

 FileReader讀取字符的方式二

需求:演示Reader中的read(char[]);讀取方法。 這種讀取的效率要比第一種高的多。

FileReader fr  = new FileReader("tempfile\\demo.txt");

//創建一個字符數組。 

char[] buf = new char[1024];

//調用了Reader中的read(char[])方法。

//將讀取到的字符存儲到了數組中,並返回了讀到的個數 。

// int len1 = fr.read(buf);

// System.out.println(len1+":"+new String(buf,0,len1));

// int len2 = fr.read(buf);

// System.out.println(len2+":"+new String(buf,0,len2));

// int len3 = fr.read(buf);

// System.out.println(len3+":"+new String(buf,0,len3));

// int len4 = fr.read(buf);

// System.out.println(len4+":"+new String(buf));

用循環

int len = 0;

while((len=fr.read(buf))!=-1){

System.out.println(new String(buf,0,len));

}

fr.close();

}

六、複製文本文件

練習:將c盤的一個文本文件複製到d盤。

思路:

1c盤的文件是一個數據的源。

複製到的d盤,說明d盤是數據的存儲的目的。該目的中應該有一個文件。

2,先讀取c盤的文件。將讀取到的數據寫入到目的地中。

3,既然是操作文本文件,只要使用字符流即可。 

方式一:讀一個 寫一個 效率低

public static void main(String[] args) throws IOException {

//1,創建字符讀取流對象和源相關聯。 

FileReader fr = new FileReader("tempfile\\IO.txt");

//2,創建字符輸出流對象,明確要存儲數據的目的。

FileWriter fw = new FileWriter("tempfile\\copy_demo.txt");

//3,進行讀寫操作。讀取一個,就寫入一個。

int ch = 0;

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

fw.write(ch);

}

//4,關閉資源。

fw.close();

fr.close();

}

方式二 :先將硬盤上的源文件數據通過輸入流存儲到內存中創建的緩存區,再從緩存區通過輸出流寫入目的文件中。效率高

使用緩衝區數組。

使用的就是可以操作數組的讀寫方法。

//1,定義字符輸入流和字符輸出流的引用。 

FileReader fr = null;

FileWriter fw = null;

try {

//2,對流對象進行初始化。

fr = new FileReader("tempfile\\demo.txt");

fw = new FileWriter("tempfile\\copy_demo2.txt");

//3,定義一個數組緩衝區。用於緩衝讀取到的數據。 

char[] buf = new char[1024];

//4,讀寫操作。 

int len = 0;

while((len = fr.read(buf))!=-1){

fw.write(buf,0,len);讀入len個,就寫len個字符

}

} catch (Exception e) {

System.out.println(e.toString());

}finally{

if(fw!=null)

try {

fw.close();

} catch (IOException e) {

throw new RuntimeException("寫入關閉失敗");

}

if(fr!=null)

try {

fr.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

七、字符串的緩衝區。BufferedWriter

緩衝區給給流的操作動作(讀寫)提高效率.所以緩衝區的對象建立必須要有流對象。

public static void main(String[] args) throws IOException {

//創建一個流對象。

FileWriter fw = new FileWriter("tempfile\\buf.txt");

//爲了提高效率。創建緩衝區對象,並和要被提高效率的流相關聯。 

BufferedWriter bufw = new BufferedWriter(fw);

//接下來就使用緩衝區的方法。因爲緩衝區的操作的都是數組中的元素的高效方法。

bufw.write("abcde");

bufw.newLine();換行=System.getProperty("line.separator");

bufw.write("xixixi");

//要對緩衝區進行刷新。記住:一般只要使用了緩衝區,就一定要刷新。 

bufw.flush();

//關閉緩衝區。 

bufw.close();//問:還用關閉fw.close()?不用,因爲關閉緩衝區,其實就是在關閉緩衝區關聯的流。

}

八、字符串的緩衝區BufferedReader

演示BufferedReader 

1,先有字符讀取流。

2,該類有一個特有方法。readLine().一次讀一行。 

//創建讀取流對象和文件相關聯。 

FileReader fr = new FileReader("tempfile\\buf.txt");

//創建讀取緩衝區對象和流對象關聯,對其進行高效操作。

BufferedReader bufr = new BufferedReader(fr);

// String line1 = bufr.readLine();

// System.out.println("line1:"+line1);

// String line2 = bufr.readLine();

// System.out.println("line2:"+line2);

// String line3 = bufr.readLine();

// System.out.println("line3:"+line3);

// String line4 = bufr.readLine();

// System.out.println("line4:"+line4);

// String line5 = bufr.readLine();

// System.out.println("line5:"+line5);

String line = null;

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

System.out.print(line);

}

bufr.close();

}

九、 使用緩衝區對文本文件進行復制。 該緩衝區也只能對文本文件

BufferedReader bufr = null;

BufferedWriter bufw = null;

try {

bufr = new BufferedReader(new FileReader("tempfile\\IO.txt"));

bufw = new BufferedWriter(new FileWriter("tempfile\\copy_buf.txt"));

//讀寫行的操作。 

String line = null;

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

bufw.write(line);

bufw.newLine();

bufw.flush();

catch (Exception e) {

System.out.println(e.toString());

}finally{

if(bufw!=null)後開先關

try {

bufw.close();

} catch (IOException e) {

e.printStackTrace();

}

if(bufr!=null)

try {

bufr.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

----------- android培訓java培訓、java學習型技術博客、期待與您交流! ------------


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