一、概述
流:代表任何有能力產出數據的數據源對象或者是有能力接受數據的接收端對象 ;其作用是為數據源和目的地建立一個輸送通道。
IO流:是程序中一套用於數據傳輸的機制。IO流是Input流和Output流的簡稱。流的輸入輸出是以程序為參照物。
1、輸入流
數據從外部流向程序。例如讀取文件,就是從外部流入程序。
2、輸出流
數據從程序流向外部。例如將程序中的數據寫入到文件中。
二、輸入輸出流的分類
1、根據方向可分為:輸入流和輸出流
2、根據形式:分為字符流(字符類型文件:txt、java、html等)和字節流(圖片、視頻、音頻等)。
3、四大基本流都是抽象類,都不能直接創建對象。
4、數據的來源/目的地:磁盤、網絡、內存和外部設備。
三、文件字符流
1、從文件中讀取數據:FileReader類
FileReader類時Reader的一個實現子類。FileReader對象中常用的是read方法,返回讀取的字符串個數。
不傳入數組,源碼中會自動創建一個長度為1的數組,將讀取值放入到數組中,返回讀取到的字符值;傳入數組,底層會將讀取到的字符放入到對應數組中,並返回讀取到的字符個數。
示例如下:
//1.每次讀取一個字符
//創建了一個輸入流對象指向D盤下的a.txt //文件字符輸入流沒有緩沖區 FileReader reader = new FileReader("D:\\a.txt"); //讀取數據 //每次只讀取一個字符,所以返回值也就是表示讀取到的這個字符 // int i1 = reader.read(); // System.out.println(i1); //定義一個變量記錄每次讀取的字符 int i; //讀取到末尾會返回 -1 //這種寫法是錯誤的,表示讀一個跳一個 // while((i = reader.read()) != -1) { // System.out.println(reader.read()); // } // while((i = reader.read()) != -1) { System.out.println(i); } //關流 reader.close(); //2.每次讀取多個字符
FileReader reader = new FileReader("D:\\a.txt"); //定義一個字符數組作為緩沖區 char[] cs = new char[5]; //將數據讀取到緩沖區 // reader.read(cs); // System.out.println(new String(cs)); //返回值表示本次讀取到的字符個數 //定義一個變量記錄讀取的個數; //文件中一共有11個字符 //第一次讀取的時候,讀取到了5個字符,所以len的值為5 //第二次讀取的時候,讀取到了5個字符,所以len的值為5 //第三次讀取的時候,讀取到了1個字符,所以len的值為1 //第四次讀取的時候,讀取到了文件末尾,所以len的值為-1 int len; //將讀取到的數據放到數組中,而返回值表示王數組中放的字符個數 while((len = reader.read(cs)) != -1) { //String(value, offset, len) //從value數組的第offset為開始,將len個元素轉為字符串 System.out.println(new String(cs, 0 , len)); } reader.close();
2、向txt文件中寫入字符串 --FileWriter
FileWriter類時Writer的一個實現子類。FileWriter對象中常用的是write方法,表示將數據寫入到文件中。
示例如下:
//創建一個新文件 //如果原文件不存在,則操作創建的這個新文件 //如果源文件已存在,則利用新文件覆蓋源文件 FileWriter writer = new FileWriter("D:\\a.txt"); //寫出數據 //在寫數據的時候,這個數據並不直接寫到文件中而是先寫到緩沖區中 //當緩沖區寫滿了之后,再將緩沖區中的數據寫入到文件中 //在緩沖區沒有寫滿的時候,程序就已經結束 //結果導致數據死在了緩存區 writer.write("detgagf"); //沖刷緩沖區 //將數據從緩沖區中沖到文件中 writer.flush(); //關閉流 //為了釋放文件以允許別的流來操作這個文件 //流一旦關閉,就不能再次開啟 //close之前,流自動進行一次flush操作,以避免有數據死在緩沖區 writer.close(); //清空引用將其標記為垃圾對象 writer = null;
四、文件字節流
1、文件字節輸入流 FileInputStream
FileInputStream類時InputStream的一個實現子類。FileInputStream對象中常用的是write方法,表示將數據寫入到文件中。 文件字節流沒有緩沖區,可定義字節數組作為緩沖區。示例如下
FileInputStream in = new FileInputStream("D:\\b.txt"); //讀取到的是字節 //定義一個字節數組作為緩沖區 byte[] bs = new byte[10]; int len; while((len = in.read(bs)) != -1) { System.out.println(new String(bs, 0 , len)); } in.close();
2、文件字節輸出流 FileOutputStream
FileOutputStream類時OutputStream的一個實現子類。FileOutputStream對象中常用的是write方法,表示將數據寫入到文件中。可以定義一個字節數組作為緩沖區。
示例如下:
FileOutputStream fs = new FileOutputStream("D:\\b.txt"); //寫出數據 //字節輸出流沒有緩沖區 fs.write("abc".getBytes()); //關流 fs.close();
五、緩沖流
1、字符輸入緩沖流 BufferedReader
在構建的時候需要傳入一個Reader對象。真正讀取數據依靠的是傳入的這個Reader對象,BufferedReader從Reader對象中獲取數據提取到緩沖區。其本質是FileReader的一個包裝類。省去了程序員人為為FileReader提供數組緩沖區的步驟。
示例如下:
//真正讀取文件的是FileReader //FileReader本身沒有緩沖區 FileReader reader = new FileReader("D:\\a.txt"); //BufferedReader將FileReader讀取的數據進行緩沖 //BufferedReader提供緩沖區 BufferedReader br = new BufferedReader(reader); //讀取一行 //String str = br.ReadLine(); // System.out.println(str); //定義一個變量用來記錄讀取的每一行數據 String str; //如果讀取到末尾,返回的是null while((str = br.readLine()) != null) { System.out.println(str); } //關流 只關閉外層流就行 br.close();
2、字符輸出緩沖流 --BufferedWriter
提供了一個更大的緩沖區,其中提供了一個newLine()方法,用於進行換行操作,以屏蔽不同操作系統的差異性。
示例如下:
//真正向文件中寫數據的流是FileWirter //BufferedWriter提供了一個更大的緩沖區 BufferedWriter writer = new BufferedWriter(new FileWriter("D:c.txt")); writer.write("sdsakj"); //在Windows中,換行一般用\r\n //在linux中,換行只用\n //進行換行,屏蔽不同操作系統的差異性 writer.newLine(); writer.write("4564561"); writer.close();
六、流中的異常處理
1、無論流操作成功與否,關流操作都得發生,所以需要將關流操作放到finally代碼塊中。
2、為了讓流對象在finally依然能夠使用,所以需要將流對象放在try之外聲明,並且要賦值為null,然后放在try之內進行實際的初始化過程。
3、在關流之前要判斷對象是否初始化成功,實際上就是判斷流對象是否為null;
4、因為關流有可能失敗,此時流會依然占用文件,所以需要將流對象置為null,標記為垃圾對象進行強制回收以釋放內存;
5、如果流有緩沖區,那么為了防止關流失敗導致沒有進行自動沖刷,所以需要手動沖刷一次,以防止有數據死在緩沖區而產生數據丟失。
流異常處理實例如下:
//2.需要將流對象放在try之外聲明並且賦值為null FileWriter writer = null; try { // 2.將流對象放在try之內進行初始化 writer = new FileWriter("F:\\a.txt"); writer.write("積分聖誕節"); //5.為了防止關流失敗沒有自動flush而導致數據產生丟失 writer.flush(); } catch (IOException e) { e.printStackTrace(); } finally { //3.在關流之前要判斷對象是否初始化成功,實際上就是判斷流對象是否為null if(writer != null) { try {
//1.無論寫流成功還是失敗,都需要關流 writer.close(); } catch (IOException e) { e.printStackTrace(); } finally { //4.如果關流失敗,將該流標記為垃圾對象,強制回收 //如果關流成功,將該流標記為垃圾對象,釋放內存 writer = null; } } }