對(duì)象流
?我們前邊學(xué)到的數(shù)據(jù)流只能實(shí)現(xiàn)對(duì)基本數(shù)據(jù)類型和字符串類型的讀寫杰妓,并不能讀取對(duì)象(字符串除外)雾棺,如果要對(duì)某個(gè)對(duì)象進(jìn)行讀寫操作念链,我們需要學(xué)習(xí)一對(duì)新的處理流:ObjectInputStream/ObjectOutputStream
為什么序列化
序列化以后的對(duì)象可以保存到磁盤上哑了,也可以在網(wǎng)絡(luò)上傳輸搀缠,使得不同的計(jì)算機(jī)可以共享對(duì)象.(序列化的字節(jié)序列是平臺(tái)無關(guān)的)
對(duì)象序列化的條件
只有實(shí)現(xiàn)了Serializable接口的類的對(duì)象才可以被序列化硅确。Serializable接口中沒有任何的方法目溉,實(shí)現(xiàn)該接口的類不需要實(shí)現(xiàn)額外的方法明肮。如果對(duì)象的屬性是對(duì)象,屬性對(duì)應(yīng)類也必須實(shí)現(xiàn)Serializable
注意
? ? ? 1. 對(duì)象流不僅可以讀寫對(duì)象缭付,還可以讀寫基本數(shù)據(jù)類型柿估。
? ? ??2. 使用對(duì)象流讀寫對(duì)象時(shí),該對(duì)象必須序列化與反序列化陷猫。
? ? ??3. 系統(tǒng)提供的類(如Date等)已經(jīng)實(shí)現(xiàn)了序列化接口秫舌,自定義類必須手動(dòng)實(shí)現(xiàn)序列化接口。
代碼練習(xí):
字節(jié)數(shù)組流
?ByteArrayInputStream和ByteArrayOutputStream經(jīng)常用在需要流和數(shù)組之間轉(zhuǎn)化的情況!
? ? ??說白了绣檬,F(xiàn)ileInputStream是把文件當(dāng)做數(shù)據(jù)源足陨。ByteArrayInputStream則是把內(nèi)存中的”某個(gè)字節(jié)數(shù)組對(duì)象”當(dāng)做數(shù)據(jù)源。
字節(jié)數(shù)組流的作用娇未?
ByteArrayInputStream 序列化輸出時(shí)以字節(jié)數(shù)組的形式傳輸墨缘,提高網(wǎng)絡(luò)傳輸?shù)男?/p>
課堂代碼:
?序列化和反序列化
兩個(gè)進(jìn)程遠(yuǎn)程通信時(shí),彼此可以發(fā)送各種類型的數(shù)據(jù)零抬。 無論是何種類型的數(shù)據(jù)飒房,都會(huì)以二進(jìn)制序列的形式在網(wǎng)絡(luò)上傳送。比如媚值,我們可以通過http協(xié)議發(fā)送字符串信息;我們也可以在網(wǎng)絡(luò)上直接發(fā)送Java對(duì)象。發(fā)送方需要把這個(gè)Java對(duì)象轉(zhuǎn)換為字節(jié)序列护糖,才能在網(wǎng)絡(luò)上傳送;接收方則需要把字節(jié)序列再恢復(fù)為Java對(duì)象才能正常讀取褥芒。
? ? ??把Java對(duì)象轉(zhuǎn)換為字節(jié)序列的過程稱為對(duì)象的序列化。把字節(jié)序列恢復(fù)為Java對(duì)象的過程稱為對(duì)象的反序列化嫡良。
? ? ??對(duì)象序列化的作用有如下兩種:
? ? ??1. 持久化: 把對(duì)象的字節(jié)序列永久地保存到硬盤上锰扶,通常存放在一個(gè)文件中,比如:休眠的實(shí)現(xiàn)寝受。以后服務(wù)器session管理坷牛,hibernate將對(duì)象持久化實(shí)現(xiàn)。
? ? ??2. 網(wǎng)絡(luò)通信:在網(wǎng)絡(luò)上傳送對(duì)象的字節(jié)序列很澄。比如:服務(wù)器之間的數(shù)據(jù)通信京闰、對(duì)象傳遞。
列化與反序列化的內(nèi)容甩苛?
? ObjectOutputStream代表對(duì)象輸出流蹂楣,它的writeObject(Object obj)方法可對(duì)參數(shù)指定的obj對(duì)象進(jìn)行序列化,把得到的字節(jié)序列寫到一個(gè)目標(biāo)輸出流中讯蒲。
?ObjectInputStream代表對(duì)象輸入流痊土,它的readObject()方法從一個(gè)源輸入流中讀取字節(jié)序列,再把它們反序列化為一個(gè)對(duì)象墨林,并將其返回赁酝。
序列化涉及的類和接口
?ObjectOutputStream代表對(duì)象輸出流犯祠,它的writeObject(Object obj)方法可對(duì)參數(shù)指定的obj對(duì)象進(jìn)行序列化,把得到的字節(jié)序列寫到一個(gè)目標(biāo)輸出流中酌呆。
? ? ??ObjectInputStream代表對(duì)象輸入流衡载,它的readObject()方法從一個(gè)源輸入流中讀取字節(jié)序列,再把它們反序列化為一個(gè)對(duì)象肪笋,并將其返回月劈。
? ? ??只有實(shí)現(xiàn)了Serializable接口的類的對(duì)象才能被序列化。 Serializable接口是一個(gè)空接口藤乙,只起到標(biāo)記作用猜揪。
裝飾器模式
裝飾器模式是GOF23種設(shè)計(jì)模式中較為常用的一種模式。它可以實(shí)現(xiàn)對(duì)原有類的包裝和裝飾坛梁,使新的類具有更強(qiáng)的功能而姐。
? ? ??我這里有智能手機(jī)iphone, 我們可以通過加裝投影組件,實(shí)現(xiàn)原有手機(jī)功能的擴(kuò)展划咐。這就是一種“裝飾器模式”拴念。 我們?cè)谖磥斫o普通人加裝“外骨骼”裝飾,讓普通人具有力扛千斤的能力褐缠,也是一種“裝飾器模式”政鼠。
代碼練習(xí):
Apache IOUtils和FileUtils
?JDK中提供的文件操作相關(guān)的類,但是功能都非扯游海基礎(chǔ)公般,進(jìn)行復(fù)雜操作時(shí)需要做大量編程工作。實(shí)際開發(fā)中胡桨,往往需要你自己動(dòng)手編寫相關(guān)的代碼官帘,尤其在遍歷目錄文件時(shí),經(jīng)常用到遞歸昧谊,非常繁瑣刽虹。 Apache-commons工具包中提供了IOUtils/FileUtils,可以讓我們非常方便的對(duì)文件和目錄進(jìn)行操作呢诬。 本文就是讓大家對(duì)IOUtils/FileUtils類有一個(gè)全面的認(rèn)識(shí)涌哲,便于大家以后開發(fā)與文件和目錄相關(guān)的功能。
? ? ??Apache IOUtils和FileUtils類庫(kù)為我們提供了更加簡(jiǎn)單尚镰、功能更加強(qiáng)大的文件操作和IO流操作功能膛虫。
FileUtils
FieUtils類中常用方法的介紹
? ? ??打開FileUtils的api文檔,我們抽出一些工作中比較常用的方法钓猬,進(jìn)行總結(jié)和講解稍刀。總結(jié)如下:
? ? ??cleanDirectory:清空目錄,但不刪除目錄账月。
? ? ??contentEquals:比較兩個(gè)文件的內(nèi)容是否相同综膀。
? ? ??copyDirectory:將一個(gè)目錄內(nèi)容拷貝到另一個(gè)目錄【殖荩可以通過FileFilter過濾需要拷貝的 文件剧劝。
? ? ??copyFile:將一個(gè)文件拷貝到一個(gè)新的地址。
? ? ??copyFileToDirectory:將一個(gè)文件拷貝到某個(gè)目錄下抓歼。
? ? ??copyInputStreamToFile:將一個(gè)輸入流中的內(nèi)容拷貝到某個(gè)文件讥此。
? ? ??deleteDirectory:刪除目錄。
? ? ??deleteQuietly:刪除文件谣妻。
? ? ??listFiles:列出指定目錄下的所有文件萄喳。
? ? ??openInputSteam:打開指定文件的輸入流。
? ? ??readFileToString:將文件內(nèi)容作為字符串返回蹋半。
? ? ??readLines:將文件內(nèi)容按行返回到一個(gè)字符串?dāng)?shù)組中他巨。
? ? ??size:返回文件或目錄的大小。
? ? ??write:將字符串內(nèi)容直接寫到文件中减江。
? ? ??writeByteArrayToFile:將字節(jié)數(shù)組內(nèi)容寫到文件中染突。
? ? ??writeLines:將容器中的元素的toString方法返回的內(nèi)容依次寫入文件中。
? ? ??writeStringToFile:將字符串內(nèi)容寫到文件中辈灼。
IOUtils
IOUtils類中常用方法
??1. buffer方法:將傳入的流進(jìn)行包裝份企,變成緩沖流。并可以通過參數(shù)指定緩沖大小巡莹。
? ? ??2. closeQueitly方法:關(guān)閉流司志。
? ? ??3. contentEquals方法:比較兩個(gè)流中的內(nèi)容是否一致。
? ? ??4. copy方法:將輸入流中的內(nèi)容拷貝到輸出流中榕莺,并可以指定字符編碼。
? ? ??5. copyLarge方法:將輸入流中的內(nèi)容拷貝到輸出流中棵介,適合大于2G內(nèi)容的拷貝钉鸯。
? ? ??6. lineIterator方法:返回可以迭代每一行內(nèi)容的迭代器。
? ? ??7. read方法:將輸入流中的部分內(nèi)容讀入到字節(jié)數(shù)組中邮辽。
? ? ??8. readFully方法:將輸入流中的所有內(nèi)容讀入到字節(jié)數(shù)組中唠雕。
? ? ??9. readLine方法:讀入輸入流內(nèi)容中的一行。
? ? ??10. toBufferedInputStream吨述,toBufferedReader:將輸入轉(zhuǎn)為帶緩存的輸入流岩睁。
? ? ??11. toByteArray,toCharArray:將輸入流的內(nèi)容轉(zhuǎn)為字節(jié)數(shù)組揣云、字符數(shù)組捕儒。
? ? ??12. toString:將輸入流或數(shù)組中的內(nèi)容轉(zhuǎn)化為字符串。
? ? ??13. write方法:向流里面寫入內(nèi)容。
? ? ??14. writeLine方法:向流里面寫入一行內(nèi)容刘莹。