欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中的字節(jié)流文件讀取教程(二)

 更新時(shí)間:2018年07月03日 09:55:39   作者:Single_Yam  
這篇文章主要給大家介紹了關(guān)于Java中字節(jié)流文件讀取的相關(guān)資料,本文屬于之前文章的延長(zhǎng)篇,有需要的朋友可以先看看上一篇文章,相信會(huì)對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

接著上篇文章,我們繼續(xù)來(lái)學(xué)習(xí) Java 中的字節(jié)流操作。

裝飾者緩沖流 BufferedInput/OutputStream

裝飾者流其實(shí)是基于一種設(shè)計(jì)模式「裝飾者模式」而實(shí)現(xiàn)的一種文件 IO 流,而我們的緩沖流只是其中的一種,我們一起來(lái)看看。

在這之前,我們使用的文件讀寫(xiě)流 FileInputStream 和 FileOutputStream 都是一個(gè)字節(jié)一個(gè)字節(jié)的從磁盤(pán)讀取或?qū)懭?,非常耗時(shí)。

而我們的緩沖流可以預(yù)先從磁盤(pán)一次性讀出指定容量的字節(jié)數(shù)到內(nèi)存中,之后的讀取操作將直接從內(nèi)存中讀取,提高效率。下面我們一起看看緩沖流的具體實(shí)現(xiàn)情況:

依然先以 BufferedInputStream 為例,我們簡(jiǎn)單提一下它的幾個(gè)核心屬性:

  • private static int DEFAULT_BUFFER_SIZE = 8192;
  • protected volatile byte buf[];
  • private static int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
  • protected int count;
  • protected int pos;
  • protected int markpos = -1;
  • protected int marklimit;

buf 就是用于緩沖讀的字節(jié)數(shù)組,它的值將隨著流的讀取而不停的被填充,繼而后續(xù)的讀操作可以直接基于這個(gè)緩沖數(shù)組。

DEFAULT_BUFFER_SIZE 規(guī)定了默認(rèn)緩沖區(qū)的大小,即 buf 的數(shù)組長(zhǎng)度。MAX_BUFFER_SIZE 指明了緩沖區(qū)的上限。

count 指向緩沖數(shù)組中最后一個(gè)有效字節(jié)索引后一位。pos 指向下一個(gè)待讀取的字節(jié)索引位置。

markpos 和 marklimit 用于重復(fù)讀操作。

接著我們看看 BufferedInputStream 的幾個(gè)示例構(gòu)造器:

public BufferedInputStream(InputStream in) {
 this(in, DEFAULT_BUFFER_SIZE);
}
public BufferedInputStream(InputStream in, int size) {
 super(in);
 if (size <= 0) {
 throw new IllegalArgumentException("Buffer size <= 0");
 }
 buf = new byte[size];
}

整體上來(lái)說(shuō),前者只需要傳入一個(gè)「被裝飾」的 InputStream 實(shí)例,并使用默認(rèn)大小的緩沖區(qū)。后者則可以顯式指明緩沖區(qū)的大小。

除此之外,super(in) 會(huì)將這個(gè) InputStream 實(shí)例保存進(jìn)父類 FilterInputStream 的 in 屬性字段中,并且所有實(shí)際的磁盤(pán)讀操作都由這個(gè) InputStream 實(shí)例發(fā)出。

下面我們來(lái)看最重要的讀操作以及緩沖區(qū)是如何被填充的。

public synchronized int read() throws IOException {
 if (pos >= count) {
 fill();
 if (pos >= count)
  return -1;
 }
 return getBufIfOpen()[pos++] & 0xff;
}

這個(gè)方法想必大家已經(jīng)很熟悉了,從流中讀取下一個(gè)字節(jié)并返回,但細(xì)節(jié)上的實(shí)現(xiàn)還是稍稍有些不同。

count 指向了緩沖數(shù)組中有效字節(jié)索引后一位置處,pos 指向下一個(gè)待讀取的字節(jié)索引位置。理論上 pos 是不可能大于 count 的,最多等于。

如果 pos 等于 count,那說(shuō)明緩沖數(shù)組中所有有效字節(jié)都已經(jīng)被讀取過(guò)了,此時(shí)即需要丟棄緩沖區(qū)中那些「無(wú)用」的數(shù)據(jù),從磁盤(pán)重新加載一批新數(shù)據(jù)填充緩沖區(qū)。

而事實(shí)上,fill 方法就是做的這個(gè)事情,它的代碼比較多,就不帶大家去解析了,你理解了它的作用,想必分析它的實(shí)現(xiàn)也是容易的。

如果 fill 方法調(diào)用之后,pos 依然 等于 count,那么說(shuō)明 InputStream 實(shí)例并沒(méi)有從流中讀取出任何數(shù)據(jù),也即文件流中無(wú)數(shù)據(jù)可讀。關(guān)于這一點(diǎn),參見(jiàn) fill 方法 246 行。

總的來(lái)說(shuō),如果成功填充了緩沖區(qū),那么我們的 read 方法將直接從緩沖區(qū)取出一個(gè)字節(jié)返回給調(diào)用者。

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

這個(gè)方法也是「熟人」了,不再多余的解釋了,實(shí)現(xiàn)是類似的。

skip 方法用于跳過(guò)指定長(zhǎng)度的字節(jié)數(shù)進(jìn)行文件流的繼續(xù)讀?。?/p>

public synchronized long skip(long n){
 //.....
}

注意一點(diǎn)的是,skip 方法盡量去跳過(guò) n 個(gè)字節(jié),但不保證一定跳過(guò) n 個(gè)字節(jié),方法返回的是實(shí)際跳過(guò)的字節(jié)數(shù)。如果緩沖數(shù)組中剩余可用字節(jié)數(shù)小于 n,那么最終將跳過(guò)緩沖數(shù)組中實(shí)際可跳過(guò)的字節(jié)數(shù)。

最后要說(shuō)一說(shuō)這個(gè) close 方法:

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;
 }
 // Else retry in case a new buf was CASed in fill()
 }
}

close 方法將賦空「被裝飾者」流,并調(diào)用它的 close 方法釋放相關(guān)資源,最終也會(huì)清空緩沖數(shù)組所占用的內(nèi)存空間。

BufferedInputStream 提供了讀緩沖能力,而 BufferedOutputStream 則提供了寫(xiě)緩沖能力,即內(nèi)存的寫(xiě)操作并不會(huì)立馬更新到磁盤(pán),暫時(shí)保存在緩沖區(qū),待緩沖區(qū)滿時(shí)一并寫(xiě)入。

protected byte buf[];

protected int count;

buf 代表了內(nèi)部緩沖區(qū),count 表示緩沖區(qū)中實(shí)際數(shù)據(jù)容量,即 buf 中有效字節(jié)數(shù),而不是 buf 數(shù)組長(zhǎng)度。

public BufferedOutputStream(OutputStream out) {
 this(out, 8192);
}

public BufferedOutputStream(OutputStream out, int size) {
 super(out);
 if (size <= 0) {
 throw new IllegalArgumentException("Buffer size <= 0");
 }
 buf = new byte[size];
}

一樣的實(shí)現(xiàn)思路,必須提供的是一個(gè) OutputStream 輸出流實(shí)例,也可以選擇性指明緩沖區(qū)大小。

public synchronized void write(int b) throws IOException {
 if (count >= buf.length) {
 flushBuffer();
 }
 buf[count++] = (byte)b;
}

寫(xiě)方法將首先檢查緩沖區(qū)是否還能容納本次寫(xiě)操作,如果不能將發(fā)起一次磁盤(pán)寫(xiě)操作,將緩沖區(qū)數(shù)據(jù)全部寫(xiě)入磁盤(pán)文件,否則將優(yōu)先寫(xiě)入緩沖區(qū)。

當(dāng)然,BufferedOutputStream 也提供了 flush 方法向外提供接口,也即不一定非要等到緩沖區(qū)滿了才向磁盤(pán)寫(xiě)數(shù)據(jù),你也可以顯式的調(diào)用該方法讓它清空緩沖區(qū)并更新磁盤(pán)文件。

public synchronized void flush() throws IOException {
 flushBuffer();
 out.flush();
}

關(guān)于緩沖流,核心內(nèi)容介紹如上,這是一種能夠顯著提升效率的流,通過(guò)它,能夠減少磁盤(pán)訪問(wèn)次數(shù),提升程序執(zhí)行效率。

有關(guān)對(duì)象序列化流 ObjectInput/OutputStream 以及基于基本類型的裝飾者流 DataInput/OutputStream 我們這里暫時(shí)不做討論。待到我們學(xué)習(xí)序列化的時(shí)候,再回頭討論這兩個(gè)字節(jié)流。

文章中的所有代碼、圖片、文件都云存儲(chǔ)在我的 GitHub 上:

(https://github.com/SingleYam/overview_java)

大家也可以選擇通過(guò)本地下載。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • idea開(kāi)啟熱部署Devtools的步驟詳解

    idea開(kāi)啟熱部署Devtools的步驟詳解

    當(dāng)我們?cè)?nbsp;idea 中修改代碼的時(shí)候,idea 并不會(huì)自動(dòng)的重啟去響應(yīng)我們修改的內(nèi)容,而是需要我們手動(dòng)的重新啟動(dòng)項(xiàng)目才可以生效,這個(gè)是非常不方便,但是可以在 idea 中開(kāi)啟這個(gè)自動(dòng)熱部署的功能,本文給大家介紹了idea開(kāi)啟熱部署Devtools的步驟,需要的朋友可以參考下
    2024-03-03
  • spring如何使用命名空間p簡(jiǎn)化bean的配置

    spring如何使用命名空間p簡(jiǎn)化bean的配置

    這篇文章主要介紹了spring如何使用命名空間p簡(jiǎn)化bean的配置,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • Java 并行數(shù)據(jù)處理和性能分析

    Java 并行數(shù)據(jù)處理和性能分析

    這篇文章主要介紹了Java 并行數(shù)據(jù)處理和性能分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-10-10
  • 理解Java當(dāng)中的回調(diào)機(jī)制(翻譯)

    理解Java當(dāng)中的回調(diào)機(jī)制(翻譯)

    今天我要和大家分享一些東西,舉例來(lái)說(shuō)這個(gè)在JavaScript中用的很多。我要講講回調(diào)(callbacks)。你知道什么時(shí)候用,怎么用這個(gè)嗎?你真的理解了它在java環(huán)境中的用法了嗎?當(dāng)我也問(wèn)我自己這些問(wèn)題,這也是我開(kāi)始研究這些的原因
    2014-10-10
  • Mybatis集成到Spring容器的詳細(xì)步驟

    Mybatis集成到Spring容器的詳細(xì)步驟

    在現(xiàn)在的JavaEE開(kāi)發(fā)過(guò)程中,我們經(jīng)常會(huì)使用到Spring+SpringMVC+Mybatis這個(gè)組合,那么Mybatis是如何集成到Spring中的呢,下面通過(guò)實(shí)例代碼給大家詳細(xì)講解,感興趣的朋友跟隨小編一起看看吧
    2024-03-03
  • Java中的 FilterInputStream簡(jiǎn)介_(kāi)動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java中的 FilterInputStream簡(jiǎn)介_(kāi)動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    FilterInputStream 的作用是用來(lái)“封裝其它的輸入流,并為它們提供額外的功能”。接下來(lái)通過(guò)本文給大家分享Java中的 FilterInputStream簡(jiǎn)介,感興趣的朋友一起學(xué)習(xí)吧
    2017-05-05
  • JVM,JRE和JDK的區(qū)別小結(jié)

    JVM,JRE和JDK的區(qū)別小結(jié)

    在Java環(huán)境配置和項(xiàng)目啟動(dòng)中,JVM,JRE和JDK這三者的配置是項(xiàng)目啟動(dòng)的基礎(chǔ)保證,本文就詳細(xì)的介紹一下這三者的區(qū)別,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • spring?boot?executable?jar/war?原理解析

    spring?boot?executable?jar/war?原理解析

    spring boot里其實(shí)不僅可以直接以 java -jar demo.jar的方式啟動(dòng),還可以把jar/war變?yōu)橐粋€(gè)可以執(zhí)行的腳本來(lái)啟動(dòng),比如./demo.jar,這篇文章主要介紹了spring?boot?executable?jar/war?原理,需要的朋友可以參考下
    2023-02-02
  • IDEA插件開(kāi)發(fā)之環(huán)境搭建過(guò)程圖文詳解

    IDEA插件開(kāi)發(fā)之環(huán)境搭建過(guò)程圖文詳解

    這篇文章主要介紹了IDEA插件開(kāi)發(fā)之環(huán)境搭建過(guò)程,本文通過(guò)圖文并茂實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05
  • Java多線程與線程池技術(shù)分享

    Java多線程與線程池技術(shù)分享

    這篇文章主要介紹了Java多線程與線程池技術(shù)分享,線程池本質(zhì)是池化技術(shù)的應(yīng)用,和連接池類似,創(chuàng)建連接與關(guān)閉連接屬于耗時(shí)操作,下文相關(guān)介紹需要的小伙伴可以參考一下
    2022-03-03

最新評(píng)論