今天是我自學Java的第43天。
感謝你的觀看,謝謝你。
話不多說,開始今天的學習:
前兩天學習了兩種非常基礎的IO流:位元組流和字元流。
今天我們要繼續學習一些更強大的流:
比如能夠高效讀寫的緩沖流;能夠轉換編碼的轉換流;能夠持久化存儲對象的序列化流……等等。
不要一看流那麼多,感覺很難記,其實真心不難,無論多少流,核心都是兩類:
InputStream位元組輸入流,核心方法read(),讀硬碟資料輸入到記憶體,對應字元輸入流Reader;
OutputStream位元組輸出流,核心方法writer(),寫記憶體資料輸出到硬碟,對應字元輸出流Writer。
所有的流都是以這兩種為核心,都是由位元組輸出流和位元組輸入流演化而來,正所謂萬流歸宗就是這個道理。使用方法都是大同小異的,隻不過字首不一樣。
一、緩沖流
Buffered,翻譯為緩沖的,是以緩沖流字首為Buffered。
它也叫高效流,顧名思義,其使用起來效率很高,經常會使用到它。
它為什麼更高效?
因為用空間換時間:底層有一個8K緩沖區專門來做這件事,進而縮短時間,更加地高效。
拿一個我們現實裡的例子:電腦卡頓,我們将記憶體增加,可以在一定程度上解決卡頓。
因為同樣是一個程式,以前記憶體小,隻能用100M記憶體處理這個程式;現在記憶體大了,專門用200M記憶體來處理,是以更快了。
這就是用空間換時間。
1.位元組緩沖流
①構造方法
位元組緩沖流,它是在位元組流的基礎上建立的,是以其參數就是位元組流。
其中它還有一個構造方法,額外有一個參數size,可以設定緩沖區的大小,但一般很少使用,都會使用其預設的8K緩沖區。
②複制檔案
無論是什麼流,它複制檔案方法都是大同小異的,無外乎就是read方法,和writer方法,再加上while循環。
③關流
位元組緩沖流關閉了,其位元組流也會跟着關閉,是以上述雖然建立了4個流,但是隻用關閉緩沖流。
2.字元緩沖流
①字元緩沖輸出流
和位元組緩沖流一樣,它也是在字元流的基礎上建立的,是以其構造方法參數就是字元流。
其中有一個特有的方法叫newline(),也就是換行;
和寫入換行符System.lineSepatator()作用一樣。
②字元緩沖輸入流
構造方法一樣,不做闡述。
其中有一個特有方法readLine(),作用是一次可以讀一行。
二、轉換流
昨天學習過編碼表,編碼表就可以了解成翻譯,可以将位元組翻譯成字元。
編碼表有很多種,就好比翻譯也會有中文翻譯,英文翻譯,日文翻譯一樣。
是以編碼表不一緻的話就會出現亂碼。
轉換流,便是位元組與字元之間的轉換的橋梁,它能夠指定編碼表,防止出現亂碼。
①轉換輸入流
InputStreamReader,它是Reader的子類。
這個名稱就特有意思,InputStream位元組流,Reader字元流。
是以轉換流本質上就是從位元組流而來的字元流,在其構造方法中可以指定編碼表。
②轉換輸出流
OutputStreamReader,和輸入流是一樣的,大同小異。
轉換流一般什麼時候使用呢?
比如說,我本來一直都是用UTF-8編碼表,這有一個特殊需求,有一個特殊檔案就是要用GBK編碼表。
這種時候就可以用到轉換流,但使用不常見。
三、序列化流和反序列化流
前面學了這麼多的流,本質上都在操作位元組,字元。
現有一個問題:如何将一個自定義對象(比如說學生對象)存儲到檔案中, 并讀取出來?
序列化流就是用來解決這個問題的,序列化 :将資料結構或對象轉換成二進制串的過程,也就是寫入檔案(輸出流)。
反序列化 :二進制串轉換成資料結構或對象的過程,也就是讀取檔案(輸入流)。
序列化流和反序列化流的字首為Object,Object代表着所有對象。
1.使用前提
①實作Serializable接口
Serializable,序列化的意思,它是Java裡的一個接口。
若想要将自定義對象存儲到檔案中,該對象對應的類必須要實作該接口。
②transient關鍵字
transient,瞬态的意思。
該類的所有屬性必須是可序列化的,如果有一個屬性不需要可序列化的,則該屬性必須使用transient 關鍵字修飾,注明是瞬态的。
③序列版本号
Serializable接口給序列化的類,提供了一個序列版本号,目的在于驗證序列化的對象和對應類是否版本比對。
也就是說,哪怕類中的屬性發生了變化,在讀取檔案時(反序列化),也能根據序列版本号找到對應的對象。
2.序列化流
ObjectOutputStream類,這是一個輸出流。
序列化流,将Java對象寫出到檔案,實作對象的持久存儲。
①建立序列化流
建立一個對象,以及一個檔案obj.txt。
同時建立一個序列化流。
②寫入對象
writeObject()方法,将某個對象寫入到obj.txt檔案中。
3.反序列化流
ObjectInputStream類,這是一個輸入流。
反序列化流,将之前使用ObjectOutputStream序列化的原始資料恢複為對象。
①建立反序列化流
②讀取對象
readObject()方法,讀取對象,該對象也就是序列化存入的對象。
最後在提一個流:列印流
PrintStream:
①這是最常見的系統列印方式,會在控制台上輸出。
②建立列印流
列印流的底層也就是建立了一個FileOutputStream(位元組輸出流),詳情見④,是以位元組輸出流有的方法它也有。
其中也有println方法,也能輸入資料到對應檔案裡面。
③改變系統列印資料的流向
這個是什麼意思呢?
就是說,調用setOut(ps)後,系統列印資料不會在控制台上輸出了,而是會列印到列印流ps對應的那個檔案裡。
總結: