我們以ByteArrayInputStream,拉開對位元組類型的“輸入流”的學習序幕。
本章,我們會先對ByteArrayInputStream進行介紹,然後深入了解一下它的源碼,最後通過示例來掌握它的用法。
ByteArrayInputStream 是位元組數組輸入流。它繼承于InputStream。
它包含一個内部緩沖區,該緩沖區包含從流中讀取的位元組;通俗點說,它的内部緩沖區就是一個位元組數組,而ByteArrayInputStream本質就是通過位元組數組來實作的。
我們都知道,InputStream通過read()向外提供接口,供它們來讀取位元組資料;而ByteArrayInputStream 的内部額外的定義了一個計數器,它被用來跟蹤 read() 方法要讀取的下一個位元組。
InputStream 函數清單
ByteArrayInputStream 函數清單
InputStream是ByteArrayInputStream的父類,我們先看看InputStream的源碼,然後再學ByteArrayInputStream的源碼。
1. InputStream.java源碼分析(基于jdk1.7.40)
2. ByteArrayInputStream.java源碼分析(基于jdk1.7.40)
說明:
ByteArrayInputStream實際上是通過“位元組數組”去儲存資料。
(01) 通過ByteArrayInputStream(byte buf[]) 或 ByteArrayInputStream(byte buf[], int offset, int length) ,我們可以根據buf數組來建立位元組流對象。
(02) read()的作用是從位元組流中“讀取下一個位元組”。
(03) read(byte[] buffer, int offset, int length)的作用是從位元組流讀取位元組資料,并寫入到位元組數組buffer中。offset是将位元組寫入到buffer的起始位置,length是寫入的位元組的長度。
(04) markSupported()是判斷位元組流是否支援“标記功能”。它一直傳回true。
(05)
mark(int
readlimit)的作用是記錄标記位置。記錄标記位置之後,某一時刻調用reset()則将“位元組流下一個被讀取的位置”重置到“mark(int
readlimit)所标記的位置”;也就是說,reset()之後再讀取位元組流時,是從mark(int readlimit)所标記的位置開始讀取。
關于ByteArrayInputStream中API的詳細用法,參考示例代碼(ByteArrayInputStreamTest.java):
運作結果:
ArrayLetters=abcdefghijklmnopqrstuvwxyz
0 : 0x61
1 : 0x62
2 : 0x63
3 : 0x64
4 : 0x65
str1=klmno
str2=fghij
結果說明:
(01) ArrayLetters 是位元組數組。0x61對應的ASCII碼值是a,0x62對應的ASCII碼值是b,依次類推...
(02) ByteArrayInputStream bais = new ByteArrayInputStream(ArrayLetters); 這句話是建立“位元組流bais”,它的内容就是ArrayLetters。
(03) for (int i=0; i<LEN; i++) ; 這個for循環的作用就是從位元組流中讀取5個位元組。每次調用bais.read()就從位元組流中讀取一個位元組。
(04) bais.mark(0); 這句話就是“設定位元組流的标記”,此時标記的位置對應的值是0x66。
(05) bais.skip(5); 這句話是跳過5個位元組。跳過5個位元組後,對應的位元組流中下一個被讀取的位元組的值是0x6B。
(06) bais.read(buf, 0, LEN); 這句話是“從位元組流中讀取LEN個資料寫入到buf中,0表示從buf的第0個位置開始寫入”。
(07) bais.reset(); 這句話是将“位元組流中下一個被讀取的位置”重置到“mark()所标記的位置”,即0x66。
學完了ByteArrayInputStream輸入流。下面,我們學習與之對應的輸出流ByteArrayOutputStream。