生活随笔
收集整理的這篇文章主要介紹了
BufferedInputStream学习笔记
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
【本文轉載于http://icanfly.iteye.com/blog/1207397】
BufferedInputStream是一個帶有緩沖區域的InputStream,它的繼承體系如下:?
InputStream?
|__FilterInputStream?
??????? |__BufferedInputStream?首先了解一下FilterInputStream:?FilterInputStream通過裝飾器模式將InputStream封裝至內部的一個成員變量:? Java代碼??
protected?volatile?InputStream?in;?? 需要注意的是該成員變量使用了volatile關鍵字進行修飾,這意味著該成員變量的引用的內存可見性為多線程即時可見的。?其它地方FilterInputStream將所有的操作委托給了in這個成員進行操作。?了解了這些過后,來仔細看看BufferedInputStream的成員變量:? Java代碼??
private?static?int?defaultBufferSize?=?8192??? ?? protected?volatile?byte?buf[];??? ?? private?static?final?AtomicReferenceFieldUpdater<BufferedInputStream,?byte[]>?bufUpdater?=?AtomicReferenceFieldUpdater.newUpdater(BufferedInputStream.class,??byte[].class,?"buf")?? ?? protected?int?count;?? ?? protected?int?pos;?? ?? protected?int?markpos?=?-1;?? ?? protected?int?marklimit;?? 通過構造函數可以看到:初始化了一個byte數組作為緩沖區域? Java代碼??
public?BufferedInputStream(InputStream?in,?int?size)?{?? ????super(in);?? ????????if?(size?<=?0)?{?? ????????????throw?new?IllegalArgumentException("Buffer?size?<=?0");?? ????????}?? ????buf?=?new?byte[size];?? }?? 這個類中最為重要的方法是fill()方法,它提供了緩沖區域的讀取、寫入、區域元素的移動更新等。下面著重分析一下該方法:? Java代碼??
private?void?fill()?throws?IOException?{?? ????????byte[]?buffer?=?getBufIfOpen();?? ????if?(markpos?<?0)?{?? ??????????? ? ? ?? ????????pos?=?0;?????????? ????}else?if?(pos?>=?buffer.length){?? ????????? ????????if?(markpos?>?0)?{????? ?????????????? ?? ????????int?sz?=?pos?-?markpos;?? ?????????????????? ????????System.arraycopy(buffer,?markpos,?buffer,?0,?sz);?? ????????pos?=?sz;?? ????????markpos?=?0;?? ????????}?else?if?(buffer.length?>=?marklimit)?{?? ?????????????????? ????????????????markpos?=?-1;????? ????????pos?=?0;?? ????????}?else?{?????????? ?????????????????? ????????int?nsz?=?pos?*?2;?? ?????????????????? ????????if?(nsz?>?marklimit)?? ????????????nsz?=?marklimit;?? ????????byte?nbuf[]?=?new?byte[nsz];?? ?????????????????? ????????System.arraycopy(buffer,?0,?nbuf,?0,?pos);?? ?????????????????? ????????????????if?(!bufUpdater.compareAndSet(this,?buffer,?nbuf))?{?? ?????????????????????? ?????????????????????? ?????????????????????? ?????????????????????? ?????????????????????? ????????????????????throw?new?IOException("Stream?closed");?? ????????????????}?? ????????????????buffer?=?nbuf;?? ????????}?? ????????count?=?pos;?? ?????????? ????int?n?=?getInIfOpen().read(buffer,?pos,?buffer.length?-?pos);?? ?????????? ????????if?(n?>?0)?? ????????????count?=?n?+?pos;?? ????}?? 整個fill的過程,可以看作是BufferedInputStream對外提供滑動讀取的功能實現,通過預先讀入一整段原始輸入流數據至緩沖區中,而外界對BufferedInputStream的讀取操作實際上是在緩沖區上進行,如果讀取的數據超過了緩沖區的范圍,那么BufferedInputStream負責重新從原始輸入流中載入下一截數據填充緩沖區,然后外界繼續通過緩沖區進行數據讀取。這樣的設計的好處是:避免了大量的磁盤IO,因為原始的InputStream類實現的read是即時讀取的,即每一次讀取都會是一次磁盤IO操作(哪怕只讀取了1個字節的數據),可想而知,如果數據量巨大,這樣的磁盤消耗非常可怕。而通過緩沖區的實現,讀取可以讀取緩沖區中的內容,當讀取超過緩沖區的內容后再進行一次磁盤IO,載入一段數據填充緩沖,那么下一次讀取一般情況下就直接可以從緩沖區讀取,減少了磁盤IO。減少的磁盤IO大致可以通過以下方式計算(限read()方式):?length? 流的最終大小?bufSize 緩沖區大小?則通過緩沖區實現的輸入流BufferedInputStream的磁盤IO數為原始InputStream磁盤IO的?1/(length/bufSize)?read方法解析:該方法返回當前位置的后一位置byte值(int表示).? Java代碼??
public?synchronized?int?read()?throws?IOException?{?? ????if?(pos?>=?count)?{?? ????????????? ????????fill();?? ????????????? ????????if?(pos?>=?count)?? ????????return?-1;?? ????}?? ?????????? ????return?getBufIfOpen()[pos++]?&?0xff;?? }?? 一次讀取多個字節(盡量讀,非貪婪)? Java代碼??
private?int?read1(byte[]?b,?int?off,?int?len)?throws?IOException?{?? ????int?avail?=?count?-?pos;?? ????if?(avail?<=?0)?{?? ????????? ? ? ?? ????????if?(len?>=?getBufIfOpen().length?&&?markpos?<?0)?{?? ????????return?getInIfOpen().read(b,?off,?len);?? ????????}?? ?????????????? ????????fill();?? ????????avail?=?count?-?pos;?? ????????if?(avail?<=?0)?return?-1;?? ????}?? ????int?cnt?=?(avail?<?len)???avail?:?len;?? ?????????? ????System.arraycopy(getBufIfOpen(),?pos,?b,?off,?cnt);?? ????pos?+=?cnt;?? ????return?cnt;?? ????}?? 以下方法和上面的方法類似,唯一不同的是,上面的方法是盡量讀,讀到多少是多少,而下面的方法是貪婪的讀,沒有讀到足夠多的數據(len)就不會返回,除非讀到了流的末尾。該方法通過不斷循環地調用上面read1方法實現貪婪讀取。? Java代碼??
public?synchronized?int?read(byte?b[],?int?off,?int?len)?? ????throws?IOException?? ????{?? ????????getBufIfOpen();??? ????????if?((off?|?len?|?(off?+?len)?|?(b.length?-?(off?+?len)))?<?0)?{?? ????????throw?new?IndexOutOfBoundsException();?? ????}?else?if?(len?==?0)?{?? ????????????return?0;?? ????????}?? ?? ????int?n?=?0;?? ????????for?(;;)?{?? ????????????int?nread?=?read1(b,?off?+?n,?len?-?n);?? ????????????if?(nread?<=?0)??? ????????????????return?(n?==?0)???nread?:?n;?? ????????????n?+=?nread;?? ????????????if?(n?>=?len)?? ????????????????return?n;?? ?????????????? ????????????InputStream?input?=?in;?? ????????????if?(input?!=?null?&&?input.available()?<=?0)?? ????????????????return?n;?? ????????}?? ????}?? 略過多少字節? Java代碼??
public?synchronized?long?skip(long?n)?throws?IOException?{?? ????????getBufIfOpen();??? ????if?(n?<=?0)?{?? ????????return?0;?? ????}?? ????long?avail?=?count?-?pos;?? ??????? ????????if?(avail?<=?0)?{?? ?????????????? ?????????????? ?????????????? ????????????if?(markpos?<0)??? ????????????????return?getInIfOpen().skip(n);?? ?????????????? ?????????????? ????????????fill();?? ????????????avail?=?count?-?pos;?? ????????????if?(avail?<=?0)?? ????????????????return?0;?? ????????}?? ?????????? ????????long?skipped?=?(avail?<?n)???avail?:?n;?? ????????pos?+=?skipped;?? ????????return?skipped;?? ????}?? 估計目前可用的字節數,原始流中可用的字節數+緩沖區中可用的字節數? Java代碼??
public?synchronized?int?available()?throws?IOException?{?? ????return?getInIfOpen().available()?+?(count?-?pos);?? ????}?? 標記位置:? Java代碼??
public?synchronized?void?mark(int?readlimit)?{?? ????marklimit?=?readlimit;?? ????markpos?=?pos;?? ????}?? 重置位置:該實現清晰的表明下一讀取位置被推到了以前的標記位置,以實現重新讀取區段的功能? Java代碼??
public?synchronized?void?reset()?throws?IOException?{?? ????????getBufIfOpen();??? ????if?(markpos?<?0)?? ????????throw?new?IOException("Resetting?to?invalid?mark");?? ????pos?=?markpos;?? ????}?? 關閉流:首先通過線程安全的方式設置了內部的緩沖區引用為空,然后再對原始輸入流進行關閉。? Java代碼??
public?void?close()?throws?IOException?{?? ????????byte[]?buffer;?? ????????while?(?(buffer?=?buf)?!=?null)?{?? ????????????if?(bufUpdater.compareAndSet(this,?buffer,?null))?{?? ????????????????InputStream?input?=?in;?? ????????????????in?=?null;?? ????????????????if?(input?!=?null)?? ????????????????????input.close();?? ????????????????return;?? ????????????}?? ?????????????? ????????}?? ????} ?
總結
以上是生活随笔為你收集整理的BufferedInputStream学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。