標籤:注意 之間 統一 另一個 編碼 nic 增強 ++ append
1.IO流(資料流)主要應用概述
資料來源:儲存在裝置裡面
* IO流用來處理裝置間資料之間的傳輸
* Java對資料的操作是通過流的方式
* Java用於對流的操作的對象都在IO包
* 流按照流向分為:輸出資料流(寫動作)與輸入資料流(讀動作)(相對於程式來說)
讀寫的方式不同造成被封裝成不同的對象
* 按照一次操作資料的位元組數目:位元組流(1B)與字元流(2B)
以前無字元流:ASCII碼1B--表達英語的文字數字,隨機電腦普及,為了表示更多國家的語言,相容了許多國家的碼錶,這樣不利於資訊溝通,統一出了unicode編碼用來表示眾多語言的文字和符號,特點是任何字元用2B表示--比較浪費資源(後面會出現不同的編碼方式最佳化這些問題)。一個中文字在不同碼錶裡面編碼不一樣,所以希望在讀取文字資訊的時候按照unicode編碼方式,對於同一資訊,擷取相同的結果
所以使用字元流處理文字。
* 字元流來曆:位元組流讀取位元組資料後,不直接操作而是先查指定的編碼錶擷取對應的字,在對文字進行操作==位元組流+編碼錶
2.具體的IO對象
共性抽取--獲得IO流的根類(抽象類別)
位元組流:InputStream OutputStream
字元流:Reader Writer
其子類均是以其相應的尾碼結尾的,對象名的首碼是功能
3.傳送文字資訊 記憶體--硬碟的檔案(優先考慮字元流的輸出資料流Writer)
找到可以操作檔案的Writer
Writer-->OutputStreamWriter-->FileWriter
* 必須明確儲存資料的目的地--檔案名稱
* 檔案不存在會自動建立,檔案存在且有資料,檔案會被覆蓋(刪除+建立新檔案)
* 輸入或輸出異常--IOException最好要進行處理
具體步驟:
1.FileWriter fw = new FileWriter("demo.txt");
2.調用Writer的寫方法void write()-參數可以是字串,字元數組,int
fw.write("abcd");--此時資料被臨時儲存緩衝區
3.進行重新整理--將緩衝區流儲存在目標檔案中
fw.flush();
4.關閉Windows資源
fw.close()--一般寫在try-catch-finally(一定會執行)
close()由來--Java程式,記事本程式等寫入硬碟檔案的操作其實都是調用windows底層的輸出資料流,所以在寫操作進行完後,必須將此流佔有的資源釋放
注意:關閉資源的時候會先重新整理close(){flush()}
流關閉後不能在寫資料,但是重新整理後可以繼續寫
要實現換行,直接那作業系統的換行命令操作
追加資料FileWriter(String filename, boolean append)-追加true
close與flush區別:後者相當於開啟檔案寫儲存,後者要關閉檔案時候,詢問是否要儲存,關閉檔案。再次開啟檔案就是新的流。
4.異常處理IOException(只要讀寫就可能會發生異常)
檔案不存在,寫失敗,關閉底層資源也會拋出異常
利用try(裡面放肯發生異常的語句)-catch-finally(close())
注意:聲明在try外面,裡面進行對象的初始化
關閉資源的時候先判斷是否為空白指標,在進行關閉動作
5.從檔案中讀資料,將其列印在控制台 FileReader
read-讀單個字元,字元數組等
* 建立都檔案的對象,確定要讀取的檔案名稱和存在性
FileReader fr = new FileReader(String filename);-找不到檔案就發生異常
* 用Reader裡面的read()方法讀單個字元
fr.read()-int(0-655235 char的一個字元的範圍);讀取到結尾會返回-1表示結束
read()方法其實是和底層的作業系統關聯,讀到結尾出,把結束標識傳給JVM,然後JVM自訂一個符合傳給調用者。
* 通常將都的動作放在迴圈裡面
* 第二種讀的方法(效率比較高)
int read(char[] cbuf)--返回讀的字元的個數.結尾為-1,將讀到的字元存在字元數組裡面。注意:空格也算是一個字元。字元數組的長度固定
int num = fr.read(ch);//資料讀到字元數組裡面
System.out.println(num + " " + new String(ch));3 abc
int num1 = fr.read(ch);//資料讀到字元數組裡面 2 dec
System.out.println(num1 + " " + new String(ch));//覆蓋前兩個元素
總結上面:寫成迴圈
從硬碟上取資料必須是一個一個取,字元數組相當是取一個放進去,等達到個數後
再統一進行處理。
關於字元數組長度1024的整數倍
eg:把一個檔案複製到另一個檔案裡面--複製原理先讀後寫-字元流
1.建立讀取檔案的字元流對象
2.建立一個目的,用來儲存讀到的資料
3.頻繁的讀寫操作
4.關閉資源
注意:一次讀一寫一,累計多個後再寫
write(char[] cbuf, int off, int len) --多個讀時候寫方法的選擇
6.字元流的緩衝區--用數組來緩衝流中的資料
出現的原因:提高對資料讀寫的效率--Java將其封裝為兩個對象
對應的類:BufferedReader(字元,字元數組行)/BufferedWriter(字元,字元數組)
緩衝區的使用:要結合對應的流進行使用,在流的基礎上對流功能的增強
緩衝區:對要操作的資料進行臨時儲存,磁頭切換次數少,效率高
代碼最佳化:設計最佳化(代碼重構),效能最佳化(增加功能-緩衝區)eg:超市拿框
緩衝區必須結合流來進行操作才會起到作用--提高效率
具體寫資料流程--使用緩衝流
//建立寫成流
FileWriter fw = new FileWriter("demo3.txt");
//建立寫成字元緩衝流對象和字元寫出流進行關聯
BufferedWriter bw = new BufferedWriter(fw);
//使用緩衝流的寫方法-連續寫操作
bw.write("ggsghjdjcjmdkkdkd");
//重新整理資料到目標檔案
bw.flush();
//關閉資源--其實底層關的是fw,緩衝僅僅是提高效率
bw.close();
[字元寫入流不斷的寫資料不處理,放在寫緩衝流中在特定的時間統一操作]
換行LINE_SEPARATOR 定義該常量,傳遞給System.getProperties();-優先選擇
也可以使用方法換行bw.newLine();
字元緩衝讀取流--readLine()-String表示讀一行(行是根據斷行符號符判斷)
可以利用迴圈傳回值為null時候,控制迴圈
[讀字元流不斷的讀出資料不處理,放在緩衝流中在特定的時間統一操作]
BufferedReader重寫了父類的方法,讀的時候父類從源讀資料,緩衝區方法從緩衝區進行讀取資料--就是不需要直接讀取記憶體,而是直接操作緩衝區,為了讓使用者讀文本更便捷-讀一行--將read方法的字元進行判斷,越到換行,就停止不包含分行符號
6.類比readLine()功能的實現
* 先實現read()-在緩衝區讀
建立數組,調用FileReader的read(char[]ch),定義兩個變數分別表示數組中剩餘的字元count,和數組的角標pose.
* 當緩衝區為0時候,開始往緩衝區方資料count = r.read(buff);pose = 0
* count < 0的時候直接返回-1
* 其他情況直接取字元 int ch = buff[pose++],count--;
實現readLine()方法
* 建立新的緩衝區StringBuilder
* 迴圈加入元素調用myRead()
* 迴圈中分別判斷\r使用continue;和\n 返回字串。
* 其他情況讀到尾巴返回null
* 注意enter鍵對應的是 \r+\n 讀到\n後在會換行
7.裝飾設計模式--對某種功能的增強
緩衝區主要作用:將讀取來源資料進行儲存,提供對該緩衝區操作的方法,把讀記憶體改為讀緩衝區。緩衝區的出現對字元流的操作進行功能的提升--裝飾著模式
裝飾者模式:對已有的東西進行增強,主體還是原來的東西
裝飾者與繼承的區別:
*相同點:裝飾和繼承都能實現對功能的擴充
*對於繼承來說:首先有一個繼承體系,下面有各種子類對象,為了更好的操作並提 高效率必須在產生新的子類提供功能的擴充,這樣就會導致繼承體系的臃腫,不靈 活,關係一旦產生,關係很難去除。
* 裝飾著模式:產生新類對舊的類功能的擴充,在結合已經存在的子類對某個功能的 擴充的實現,使得類之間的關係沒有特別緊密。比較靈活
* 使用裝飾者模式的要求
裝飾者與被裝飾者具有同一個父類或同一個父介面(具有相同的方法功能的增強)
eg:BufferedReader& FileReader--Reader
8.LineNumberReader(BufferedReader子類也是裝飾者)--擷取設定當前行號
setLineNumber(int lineNumber)
getLineNumber()
BufferedReader的增強版本
9.位元組流-操作位元組、字元以及其他的媒體檔案
操作思想和字元流完全一致
* InputStram/OutputStream--位元組流用的緩衝區是位元組數組byte[]b
寫不進緩衝直接去目的地,不用重新整理,直接關閉資源。寫的是原碼
avaliable()-int 可操作的位元組數目;
* 位元組流的應用--複製mp3
1.自訂緩衝區FileInputStram 2.使用封裝的BufferedInputStram(寫要重新整理)
注意:不能用字元流讀圖片,因為字元流會把所以位元組拿到後在去查碼錶解析,但是對於文字有固定的碼錶對應,對於圖片無固定的碼錶,所以可能存在找不到對於資訊的情況,所以複製圖片不能代表原來的圖片
Java基礎總結--IO總結1