摘要:過濾器流,如等,是類庫,是為了提供一些類讓你能夠處理一些極為常見的數據格式。讀寫器,由于流和過濾器流還是僅次于處理字節,也就是二進制。過濾器流緩沖流和類將寫入的數據存儲到緩沖區中一個名為的保護字節數組字段,直到緩沖區滿或刷新輸出流。
A little older, a little wiser, but happy to see you.
——Interstellar
2018年了,再過一年就要30歲了,年齡有一些,智慧也有了一些。主要集中在技術、技術經驗和工作經驗。一直都記錄在有道云筆記里,現在拿出來分享記錄下,也希望能得到大家的feedback。
另外也想堅持做一些事情,2018年,我的目標是每天都過的有意義。
這就需要定義什么叫有意義:
每天都能按照自己,真正的自己的意愿。不受集體思想的影響。做自己!
每天都沉淀東西出來,一天天的積累。
一次以上旅游。
年底需計劃下一年的事情
所以其中一件需要積累和沉淀的就是寫作能力,或許剛開始需要參考一些書籍,但我希望能沉淀下來。所以給自己立個flag,每周在segmentfault發一篇文章。 話不多說,馬上進入正題:
Java的IO系統在學習IO之前,跟學其他新東西一樣,最核心最難的就是理解概念,特別是一堆很相近的概念,往往讓人產生困惑。如Java的IO系統,我們在這需區分以下概念:
流(Stream),是有IO系統設計者創造出來的概念,將具體設備的IO抽象為流,所以不同的設備IO對于不同的流,如FileInputStream和ByteArrayInputStream,前者的設備是操作系統的文件,后者則是操作系統的內存。
過濾器流(FilterInputStream),如BufferedInputStream等,是JavaIO類庫,是為了提供一些類讓你能夠處理一些極為常見的數據格式。如BufferedInputStream是為了解決緩沖問題,DataInputStream是為了解決Java的數據格式。
讀寫器(Reader/Writer),由于流和過濾器流還是僅次于處理字節,也就是二進制。 而處理文本,就涉及到字符編碼格式的問題。 實際上也是相當于過濾器流,也是用裝飾模式,把面向字節的接口改為面向字符的接口。
I/O對于(程序)語言設計者來說,其中一個難的任務是:創造一個好的I/O系統。
這個挑戰時來源于要覆蓋所有的可能性,不僅包括不同的I/O源和與之通訊的接受端(文件files、控制臺the console、網絡鏈接network connections等),而且還需要以多種不同的方式與它們進行通信(順序sequential、隨機讀取random-access、緩沖buffered、二進制binary、按字符character、按行by lines、按字by words等)。
為了解決這個難的任務,Java類庫的設計者創建了大量的類。也正是這么多類,導致剛學IO的人一開始就被如此多類給難倒。
自從Java1.0版本開始,Java的I/O類庫發生明顯的改變,在原來面向字節的類中添加面向字符和基于Unicode的類。在JDK 1.4中添加了NIO類(其中N代表new,過了那么多年,其實不新啦)。
因此,在充分理解IO系統和正確地運用之前,我們需要學習相當數量的類。除此之外,很有必要理解IO類庫的演變過程,或許你會這么說“不要用歷史打擾我,我只想知道怎么用”。 但問題是,如果缺乏歷史的眼光,很快我們就會對什么時候該使用哪些類,以及什么時候不該使用它們而感到困惑。
使用IO庫往往會接觸到“流”這個概念,它代表任何有能力產出數據的數據源對象或者是有能力接收數據的接收端對象。設計“流”這個概念,是為了屏蔽實際的IO設備中處理數據的細節。
InputStream和OuputStream時相當原始的類。它們可以單個或成組地讀/寫字節,但僅此而已。要確定字節的含義(比如,它們時整數還是IEEE 754浮點數或是Unicode文本),這完全由程序員和代碼來完成。不過,有一些極為常見的數據格式,如果在類中提供這些數據格式的固定實現,會很有好處。
于是Java提供了很多過濾器,可以附加到原始流中,在原始字節和各種格式之間來回轉換。
過濾器有兩個版本:過濾器流以及閱讀器和讀寫器。
過濾器流主要處理二進制數據,也就是作為字節處理。
閱讀器和書寫器主要時處理多種編碼文本,如UTF-8和ISO 8859-1。
BufferedOutputStream類將寫入的數據存儲到緩沖區中(一個名為buf的保護字節數組字段),直到緩沖區滿或刷新輸出流。
它首先嘗試從緩沖區去獲取數據,當緩存區沒有數據時,流才從底層的數據源中讀取數據。這時,它會從源讀取盡可能多的數據進入緩存區,而不管是否馬上需要所有這些數據。那些不會立刻用到的數據(已緩存的)會在以后調用read()讀取。
因為從磁盤中讀取文件時,從底層流中讀取幾百字節的數據與讀取1個字節數據的速度幾乎一樣快,因此緩沖可以顯著提高性能。
但對于網絡連接,這種效果則不明顯,在這里瓶頸往往是網絡傳送數據的速度,而不是網絡接口向程序傳送數據的速度或程序運行的速度。盡管如此,緩沖輸入沒有什么壞處,隨著網絡的速度加快會變得更為重要。
PrintStream類是大多數程序員都會遇到的第一個過濾器輸出流,因為System.out就是一個PrintStream。
PrintStream是有害的,網絡程序員應當像躲避瘟疫一樣躲避它。
第一個問題:println()方法輸出是與平臺有關的。在UNIX(包括Mac OS X)下是換行符(n),在Mac OS 9下時回車符(r),在Windows下時回車/換行對(rn)
第二個問題:PrintStream假定使用所在平臺的默認編碼方式。
第三個問題:PrintStream吞掉了所有異常。
DataInputStream和DataOutputStream提供了一些方法,可以用二進制格式讀/寫Java的基本數據類型和字符串。所用的二進制格式主要用于在兩個不同的Java程序之間交換數據(可能通過網絡鏈接、數據文件、管道或其他中間介質)。
所有數據都以big-endian格式寫入。byte會寫為1字節,short寫為2字節,int寫為4字節,long寫為8字節。浮點數和雙精浮點數分別寫為4字節和8字節的IEEE 754格式。 布爾數寫為1字節,1表示true,0表示false。字符寫為兩個無符號字節。
writeChars(String s)方法只是對String參數迭代(循環)處理,將各個字符按順序寫為一個2字節的big-endian Unicode字節(確切地講是UTF-16碼點)。
writeBytes(String s)方法迭代處理String參數,但只寫入每個字符的低字節。因此如果包含有Latin-1字符集意外的字符,其中信息將會丟失。對于一些指定了ASCII編碼的網絡協議來說,這個方法或許有用,但多數情況下都應避免使用。
writeChars和writeBytes方法都不會對輸出流的字符串的長度編碼。因此,你無法真正區分原始字符和作為字符串一部分的字符。簡單的說就是只支持ASCII編碼格式的字符串。
writeUTF(String s)方法則包括了字符串的長度。它將字符串本身用Unicode UTF-8編碼的一個變體進行編碼。由于這個變體編碼方式與大多數非Java軟件不兼容,所以應當只用于其他使用DataInputStream讀取字符串的Java程序進行數據交換。(如果Sun當初把這個方法及相應的讀取方式命名為writeString()和readString(),而不是writeUTF()和readUTF(),那就不會產生任何混淆了)。
因此,為了與其他軟件交換UTF-8文本,應使用帶適當編碼功能的InputStreamReader
許多程序員在編碼時有一個壞習慣,好像所有文本都是ASCII編碼,或者至少是該平臺的內置編碼方式。
雖然有些協議的編碼,采用ASCII編碼方式,如較老的、較簡單的網絡協議(daytime, quote of the day和charge)。
但HTTP協議和其他很多較新的協議卻不是這樣,它們允許多種本地化編碼,如K0I8-R西里爾文、Big-5中文和土耳其語使用的ISO8859-9。
Java的內置字符集時Unicode的UTF-16編碼。
Java定義了兩個抽象類,讀/寫字符的基本API,分別是java.io.Reader和java.io.Writer。
Reader和Writer最重要的具體子類是InputStreamReader和OutputStreamWriter類。InputStreamReader包含StreamDecoder類,而StreamDecoder類封裝一個底層輸入流InputStream,利用多態,可以從不同設備中讀取原始字節,然后根據指定的編碼方式,將這些字節轉換為Unicode字符。OutputStreamWriter類包含類StreamEncoder,StreamEncoder類封裝一個底層的輸出流OutputStream,利用多態,可以往不同設備中寫入數據,OutputStreamWriter從運行中的程序中接受Unicode字符,然后使用制定的編碼方式將這些字符轉為字節,再將這些字節寫入底層輸入流中。
閱讀器和讀寫器的過濾器與過濾器流一樣,Reader和Writer有很多子類可以完成特定的過濾工作,包括:
BufferedReader
BufferedWriter
LineNumberReader
PushbackReader
PrintWriter
BufferedReader和BufferedWriter使用一個內部字符數組作為緩沖區。
當程序從BufferedReader讀取時,文本會從緩沖區得到,而不是直接從底層輸入流或其他文本源讀取。當緩沖區清空時,才會去讀取文本,將文本填充此緩沖區,盡管這些文本不是全部都立即需要,這樣可以使以后的讀取速度更快。當程序寫入一個BufferedWriter時,文本被放置在緩沖區中。只有緩沖區填滿或者當書寫器顯式刷新輸出時,文本才會被移到底層輸出流或其他目標,這使得寫入也要快很多。
參考:
《Java編程思想》
《Java網絡編程》
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/68172.html
摘要:多強共存還是一家獨大,中國云計算市場的格局仍然未定,在年仍將戰事不斷。根據市場調研機構最新報告顯示,在年第三季度,中國公有云市場再現競爭格局。媒體根據營收數據計算,百度智能云已列市場前三。年的頭三個月,百度智能云在市場上繼續動作頻頻。多強共存還是一家獨大,中國云計算市場的格局仍然未定,在2019年仍將戰事不斷。根據市場調研機構IDC最新報告顯示,在2018年第三季度,中國公有云(IaaS+P...
閱讀 3329·2021-11-16 11:45
閱讀 4406·2021-09-22 15:38
閱讀 2848·2021-09-22 15:26
閱讀 3357·2021-09-01 10:48
閱讀 857·2019-08-30 15:56
閱讀 727·2019-08-29 13:58
閱讀 1495·2019-08-28 18:00
閱讀 2169·2019-08-27 10:53