----------- android培訓、java培訓、java學習型技術博客、期待與您交流! ------------
IO流用來處理設備之間的數據傳輸
Java對數據的操作是通過流的方式
Java用於操作流的對象都在IO包中
流按操作數據分爲兩種:字節流和字符流
流按流向分爲:輸入流、輸出流
一、字符流的由來:
以前處理數據都是字節數據,使用字節流技術就可以完成了。
因爲後期編碼表的不斷出現,識別某一文字的碼錶不唯一。比如中文,GBK,unicode都可以識別。
就出出現了編碼問題。
中文字節數據 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盤。
思路:
1,c盤的文件是一個數據的源。
複製到的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();
}
}
}