[六]JavaIO之 ByteArrayInputStream與ByteArrayOutputStream


 

功能簡介

 
ByteArrayInputStream 和 ByteArrayOutputStream
提供了針對於字符數組 byte [] 的標准的IO操作方式
 
image_5b976984_59d4
 
ByteArrayInputStream將會給一個byte buf[]   提供標准的IO操作方式
 
ByteArrayOutputStream則是將數據寫入到內部的字節數組中
 
 

ByteArrayInputStream 詳解


功能: 從提供的字節數組中,以IO的行為方式工作,進行讀取數據
 

ByteArrayInputStream字段

protected byte[] buf 用於保存由該流的創建者提供的 byte 數組
也就是構造方法傳入
protected int count 個數
protected int mark 流中當前的標記位置
構造時默認將 ByteArrayInputStream 對象標記在位置零處
通過 mark() 方法可將其標記在緩沖區內的另一個位置處
通過 reset() 方法將當前緩沖區位置設置為此點
protected int mark = 0;定義時設置了默認值,如果不設置將為0
protected int pos 要從輸入流緩沖區中讀取的下一個字符的索引
 
 

ByteArrayInputStream構造方法

public ByteArrayInputStream(byte[] buf) 需要傳入byte buf[] 字節數組作為他的緩沖區
當前起始下標 pos  為0
count為數組長度
mark位置為0
image_5b976984_3cbf
image_5b976984_6c8c
public ByteArrayInputStream(byte[] buf,
                            int offset,
                            int length)

傳入字節數組以及偏移量和長度
當前起始下標 pos  為 指定的偏移量
個數為offset+length 和 buf.length中小的那個
mark為偏移量起始地址
可以理解為,這個字節數組偏移量的部分才是數據源,前面都沒關系
image_5b976984_73ec
image_5b976984_7824
 
 

read方法

讀取下一個位置的字節
如果下一個位置 pos小於總個數
返回pos下標的字節數組數據
並且pos自增
image_5b976984_4062
& 0xff  :
Java中只有  有符號數,
類型提升時是按照符號位擴展的
對於正數,沒有什么影響
對於負數,按照符號位擴展和按照0位擴展區別很大

按符號位擴展,也就是補符號位,值不變
按零位擴展,也就是補零時,相當於有符號數轉變為無符號數

所以在數值計算中,直接使用類型提升,數值不變
而對於編解碼時,需要進行轉換

&0xff這種方式就是來確保是按補零擴展
0xff默認為int型,是十六進制,十進制中表示為255,二進制為32位,后八位為'1111 1111',其他24位均為0
a & 0xff 操作時,因為a為byte型,所以會將a自動轉化為int型(高位補1)
byte & 0xff操作一般將byte數據轉換成int型,最終的數據只有低8位有數據,其他位為0
簡單說就是讀取pos下標的元素,返回值為int
  
 

帶參數的read()方法
將數據讀取到b的off位置處

 

//從流中讀取數據到b[] 中,從off開始寫,寫len長度

public synchronized int read(byte b[], int off, int len) {

if (b == null) {//如果b為null 空指針

throw new NullPointerException();

} else if (off < 0 || len < 0 || len > b.length - off) {//如果偏移量小於0 或者寫入長度小於0 或者想要讀取的長度小於實際的長度了

throw new IndexOutOfBoundsException();

}



if (pos >= count) {//如果位置光標已經到了最后了,沒有數據可讀,返回-1

return -1;

}



int avail = count - pos;//可用個數為總個數count - 當前位置pos

if (len > avail) {//如果想要讀取的len比實際擁有的數據要長,那么只讀取實際的個數

len = avail;

}

if (len <= 0) {

return 0;

}

System.arraycopy(buf, pos, b, off, len);//使用本地方法拷貝數據 buf 的pos位置開始拷貝,拷貝len個,到b的off位置

pos += len;//位置光標后移

return len;

}

 


 
read方法本質很簡單
就是一個數組,讀取一個,就光標移動下一個,pos就是記住位置的變量
讀取的就是指定下標的元素
image_5b976984_3d24
 

skip

image_5b976984_9e0
image_5b976984_5055
 
 

available

本質就是個數組,所以可用個數就是總個數減去下一個字符的索引
image_5b976984_55e7
 
 

mark /markSupported /reset

ByteArrayInputStream支持mark和reset
而且 很顯然,mark方法的輸入參數是無效的
何處調用,何處就是標記點
調用reset就是pos設置到標記點

image_5b976984_5d94
為什么mark 的參數無效?
很顯然,ByteArrayInputStream是操作字符數組的,而且,這個數組不是復制而來的
是直接通過引用指向的
也就是說整個的字節數組都在隨時可訪問的范圍內,要這個參數有什么用呢
mark /markSupported /reset 三連的本質在於提供可重復讀的功能,所以對於不可逆的流需要緩存
此處天然自帶可以隨時讀取某個下標的能力
 

close

 
ByteArrayInputStream的根本在於針對給定的某個字節數組,提供IO操作方式的統一形式
就好像你寫了個方法操作字節數組一樣,完全不涉及資源
所以無需關閉任何實質內容
通過close關閉ByteArrayInputStream之后,如果再次使用這個流
並不會拋出異常
當然,流結束了,就不能再繼續使用了
 
所有方法列表
image_5b976984_53d2
 
 
 

ByteArrayOutputStream詳解

 
以IO的行為方式工作,將數據寫入到內部的字節數組中
 

ByteArrayOutputStream字段

protected byte buf[];
存儲數據的緩沖區
protected int count;
緩沖區中的有效字節數,每次寫入將會寫入到buf[count]處
 
 

ByteArrayOutputStream構造方法

 
構造方法只是設置內部字節數組這個緩沖區數據的大小
    public ByteArrayOutputStream() ;
默認長度為32位
image_5b976984_5f3
public ByteArrayOutputStream(int size) 只要參數值合法,創建指定個數的字節數組緩沖區
image_5b976984_3af3
 
 
 

write

write是輸出,參數都是他的輸出內容,只是不同的流輸出的目的不一樣,此處我們的輸出流的目的地是內部的字節數組
write(int) 將指定的字節寫入此 byte 數組輸出流
也就是寫入到內部的字節數組中
write(byte[], int, int) 將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入此 byte 數組輸出流
也就是寫入到內部的字節數組中
 
可以看得出來,他們都有使用 ensureCapacity在必要的時候進行擴展
擴展的行為是新建一個更大的,然后將原有數組元素全部拷貝過去
保證空間足夠的情況下
write(int)  就是buf[count] = (byte)b;
對於write(byte[], int, int)  則是使用System.arraycopy
image_5b976984_5bfb
 

writeTo(OutputStream)

 
因為ByteArrayOutputStream內部維護的是一個字節數組,所以可以直接作為OutputStream中write()方法的參數
代碼很簡單,就是講內部的字節數組,轉存到入參指定的輸出流中
相當於把流中的數據重寫了一份到另外的輸出流
image_5b976984_123b
 

toString()

計算機所有的數據都是二進制存儲,最小的單位是字節,字符的編碼形式也正是字節
所以,toString其實就是把字節序列進行解碼

image_5b976984_571f  
int類型入參的方法,在JDK1.8  已經棄用
toString()使用平台默認的字符集,通過解碼字節將緩沖區內容轉換為字符串
toString(String charsetName)   使用指定的 charsetName,通過解碼字節將緩沖區內容轉換為字符串
 
 
 

reset()

reset是重置的意思,ByteArrayOutputStream 使用buf[] 存儲數據,使用count指示位置
所以想要重新使用現在的緩沖區,拋棄原來所有的,只需要將count清零,每次的數據重新從0開始寫入字節數組即可
image_5b976984_7677
反正我們知道現在總共有多少有效字節,原來寫入到buf中的可能多於count的那些字節就放着好了,我們也不去使用
 

size()

count就是一直用來記錄有效個數的,所以直接返回count就是實際的size
image_5b976984_1f98
 
 

toByteArray()

轉換為字節數組,它本身就是一個字節數組
所以轉換比較簡單,只需要創建一個大小相同的字節數組,並且將數據拷貝過去即可
image_5b976984_5b2a
 

close()

ByteArrayOutputStream 寫入的是自己內部的字節數組
屬於內存數據,不涉及任何資源,所以close不需要做什么
image_5b976985_5e3f
 
 
 
 
 
 
 
 
 
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM