1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時(shí)間:8:30-17:00
      你可能遇到了下面的問(wèn)題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
      通過(guò)JDK源碼學(xué)習(xí)InputStream詳解

      概況

      創(chuàng)新互聯(lián)建站長(zhǎng)期為超過(guò)千家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為新興企業(yè)提供專業(yè)的網(wǎng)站制作、做網(wǎng)站,新興網(wǎng)站改版等技術(shù)服務(wù)。擁有十年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。

      本文主要給大家介紹了通過(guò)JDK源碼學(xué)習(xí)InputStream的相關(guān)內(nèi)容,JDK 給我們提供了很多實(shí)用的輸入流 xxxInputStream,而 InputStream 是所有字節(jié)輸入流的抽象。包括 ByteArrayInputStream 、FilterInputStream 、BufferedInputStream 、DataInputStream 和 PushbackInputStream 等等。下面話不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧。

      如何閱讀JDK源碼。

      以看核心虛擬機(jī)(hotspot)code為例介紹。

      1)熟悉虛擬機(jī)原理。調(diào)bug可以不懂原理,但是看code必須懂原理,從code里面看原理,基本不可能。hotspot的code寫(xiě)的挺亂的,想直接通過(guò)code以及code中的注釋看明白還是很困難的。所以先熟悉虛擬機(jī)的原理,再去看code,會(huì)針對(duì)性比較強(qiáng)。

      2)分模塊閱讀code。hotspot包括的模塊確實(shí)太多,我們需要分成不同的模塊各個(gè)擊破。以GC為例,hotspot中的gc算法有很多種,parallel scavenge,cms,g1…等等,先弄懂這些算法的原理,再去看code會(huì)比較快。不要看二手資料,不要看翻譯資料,推薦R大的hllvm論壇以及周志明的深入java虛擬機(jī),hotspot源碼閱讀這本書(shū)寫(xiě)的也還可以。

      繼承結(jié)構(gòu)

      --java.lang.Object
       --java.io.InputStream

      類定義

      public abstract class InputStream implements Closeable

      InputStream 被定為 public 且 abstract 的類,實(shí)現(xiàn)了Closeable接口。

      Closeable 接口表示 InputStream 可以被close,接口定義如下:

      public interface Closeable extends AutoCloseable {
        public void close() throws IOException;
      }

      主要屬性

      private static final int MAX_SKIP_BUFFER_SIZE = 2048;
      
      private static final int DEFAULT_BUFFER_SIZE = 8192;
      
      private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
      • MAX_SKIP_BUFFER_SIZE 表示輸入流每次最多能跳過(guò)的字節(jié)數(shù)。
      • DEFAULT_BUFFER_SIZE 默認(rèn)的緩沖大小。
      • MAX_BUFFER_SIZE 表示最大的緩沖數(shù)組大小,這里設(shè)置為 Integer.MAX_VALUE - 8 這里也是考慮到 JVM 能支持的大小,超過(guò)這個(gè)值就會(huì)導(dǎo)致 OutOfMemoryError。

      主要方法

      read方法

      一共有三個(gè) read 方法,其中有一個(gè)抽象的 read 方法,其余兩個(gè) read 方法都會(huì)調(diào)用這個(gè)抽象方法,該方法用于從輸入流讀取下一個(gè)字節(jié),返回一個(gè)0到255范圍的值。如果已經(jīng)到達(dá)輸入流結(jié)尾處而導(dǎo)致無(wú)可讀字節(jié)則返回-1,同時(shí),此方法為阻塞方法,解除阻塞的條件:

           1. 有可讀的字節(jié)。

           2. 檢測(cè)到已經(jīng)是輸入流的結(jié)尾了。

           3. 拋出異常。

      主要看第三個(gè) read 方法即可,它傳入的三個(gè)參數(shù),byte數(shù)組、偏移量和數(shù)組長(zhǎng)度。該方法主要是從輸入流中讀取指定長(zhǎng)度的字節(jié)數(shù)據(jù)到字節(jié)數(shù)組中,需要注意的是這里只是嘗試去讀取長(zhǎng)度為 len 的數(shù)組,但真正讀取到的數(shù)組長(zhǎng)度不一定為 len,返回值才是真正讀取到的長(zhǎng)度。

        public abstract int read() throws IOException;
      
        public int read(byte b[]) throws IOException {
          return read(b, 0, b.length);
        }
        public int read(byte b[], int off, int len) throws IOException {
          if (b == null) {
            throw new NullPointerException();
          } else if (off < 0 || len < 0 || len > b.length - off) {
            throw new IndexOutOfBoundsException();
          } else if (len == 0) {
            return 0;
          }
      
          int c = read();
          if (c == -1) {
            return -1;
          }
          b[off] = (byte)c;
      
          int i = 1;
          try {
            for (; i < len ; i++) {
              c = read();
              if (c == -1) {
                break;
              }
              b[off + i] = (byte)c;
            }
          } catch (IOException ee) {
          }
          return i;
        }

      看看它的邏輯,數(shù)組為null則拋空指針,偏移量和長(zhǎng)度超過(guò)邊界也拋異常,長(zhǎng)度為0則什么都不敢直接返回0。接著調(diào)用 read() 讀取一個(gè)字節(jié),如果為-1則說(shuō)明結(jié)束,直接返回-1。否則繼續(xù)根據(jù)數(shù)組長(zhǎng)度循環(huán)調(diào)用 read() 方法讀取字節(jié),并且填充到傳入的數(shù)組對(duì)象中,最后返回讀取的字節(jié)數(shù)。

      readAllBytes方法

      該方法從輸入流讀取所有剩余的字節(jié),在此過(guò)程是阻塞的,直到所有剩余字節(jié)都被讀取或到達(dá)流的結(jié)尾或發(fā)生異常。

      邏輯是用一個(gè) for 循環(huán)內(nèi)嵌一個(gè) while 循環(huán),while 循環(huán)不斷調(diào)用 read 方法嘗試將 DEFAULT_BUFFER_SIZE 長(zhǎng)度的字節(jié)數(shù)組填滿,一旦填滿則需要將數(shù)組容量擴(kuò)容一倍,再將原字節(jié)數(shù)組復(fù)制到新數(shù)組中,然后再通過(guò) while 循環(huán)繼續(xù)讀取,直到達(dá)到尾部才跳出 for 循環(huán),最后返回讀取到的所有字節(jié)數(shù)組。

        public byte[] readAllBytes() throws IOException {
          byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
          int capacity = buf.length;
          int nread = 0;
          int n;
          for (;;) {
            while ((n = read(buf, nread, capacity - nread)) > 0)
              nread += n;
            if (n < 0)
              break;
            if (capacity <= MAX_BUFFER_SIZE - capacity) {
              capacity = capacity << 1;
            } else {
              if (capacity == MAX_BUFFER_SIZE)
                throw new OutOfMemoryError("Required array size too large");
              capacity = MAX_BUFFER_SIZE;
            }
            buf = Arrays.copyOf(buf, capacity);
          }
          return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
        }

      readNBytes方法

      從輸入流中讀取指定長(zhǎng)度的字節(jié),而且它能保證一定能讀取到指定的長(zhǎng)度,它屬于阻塞方式,用一個(gè) while 循環(huán)不斷調(diào)用 read 讀取字節(jié),直到讀取到指定長(zhǎng)度才結(jié)束讀取。

        public int readNBytes(byte[] b, int off, int len) throws IOException {
          Objects.requireNonNull(b);
          if (off < 0 || len < 0 || len > b.length - off)
            throw new IndexOutOfBoundsException();
          int n = 0;
          while (n < len) {
            int count = read(b, off + n, len - n);
            if (count < 0)
              break;
            n += count;
          }
          return n;
        }

      available方法

      返回從該輸入流能進(jìn)行非阻塞讀取的剩余字節(jié)數(shù),當(dāng)調(diào)用 read 讀取的字節(jié)數(shù)一般會(huì)小于該值,有一些InputStream的子實(shí)現(xiàn)類會(huì)通過(guò)該方法返回流的剩余總字節(jié)數(shù),但有些并不會(huì),所以使用時(shí)要注意點(diǎn)。

      這里抽象類直接返回0,子類中重寫(xiě)該方法。

      public int available() throws IOException {
          return 0;
        }

      skip方法

      從輸入流中跳過(guò)指定個(gè)數(shù)字節(jié),返回值為真正跳過(guò)的個(gè)數(shù)。這里的實(shí)現(xiàn)是簡(jiǎn)單通過(guò)不斷調(diào)用 read 方法來(lái)實(shí)現(xiàn)跳過(guò)邏輯,但這是較低效的,子類可用更高效的方式重寫(xiě)此方法。

      下面看看邏輯,最大的跳過(guò)長(zhǎng)度不能超過(guò) MAX_SKIP_BUFFER_SIZE ,并且用一個(gè) while 循環(huán)調(diào)用 read 方法,如果遇到返回為-1,即已經(jīng)到達(dá)結(jié)尾了,則跳出循環(huán)。可以看到 skipBuffer 其實(shí)是沒(méi)有什么作用,直接讓其被 GC 即可,最后返回真正跳過(guò)的字節(jié)數(shù)。

        public long skip(long n) throws IOException {
      
          long remaining = n;
          int nr;
      
          if (n <= 0) {
            return 0;
          }
      
          int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);
          byte[] skipBuffer = new byte[size];
          while (remaining > 0) {
            nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
            if (nr < 0) {
              break;
            }
            remaining -= nr;
          }
      
          return n - remaining;
        }

      close方法

      此方法用于關(guān)閉輸入流,并且釋放相關(guān)資源 。

      public void close() throws IOException {}

      transferTo方法

      從輸入流中按順序讀取全部字節(jié)并且寫(xiě)入到指定的輸出流中,返回值為轉(zhuǎn)移的字節(jié)數(shù)。轉(zhuǎn)移過(guò)程中可能會(huì)發(fā)生不確定次的阻塞,阻塞可能發(fā)生在 read 操作或 write 操作。

      主要邏輯是用 while 循環(huán)不斷調(diào)用 read 方法操作讀取字節(jié),然后調(diào)用輸出流的 write 方法寫(xiě)入,直到讀取返回-1,即達(dá)到結(jié)尾。最后返回轉(zhuǎn)移的字節(jié)數(shù)。

        public long transferTo(OutputStream out) throws IOException {
          Objects.requireNonNull(out, "out");
          long transferred = 0;
          byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
          int read;
          while ((read = this.read(buffer, 0, DEFAULT_BUFFER_SIZE)) >= 0) {
            out.write(buffer, 0, read);
            transferred += read;
          }
          return transferred;
        }

      markSupported方法

      是否支持 mark 和 reset 操作,這里直接返回 false,子類根據(jù)實(shí)際重寫(xiě)該方法。

        public boolean markSupported() {
          return false;
        }

      mark方法

      標(biāo)記輸入流當(dāng)前位置,與之對(duì)應(yīng)的是 reset 方法,通過(guò)他們之間的組合能實(shí)現(xiàn)重復(fù)讀取操作。另外它會(huì)傳入 readlimit 參數(shù),它用于表示該輸入流中在執(zhí)行 mark 操作后最多可以讀 readlimit 個(gè)字節(jié)后才使 mark 的位置失效。

      可以看到 InputStream 的 mark 方法是什么都不做的,子類中再具體實(shí)現(xiàn)。

      public synchronized void mark(int readlimit) {}

      reset方法

      與 mark 方法對(duì)應(yīng),它可以重置輸入流的位置到上次被 mark 操作標(biāo)識(shí)的位置。InputStream 的 reset 方法直接拋出一個(gè) IOException,子類中根據(jù)實(shí)際情況實(shí)現(xiàn)。

        public synchronized void reset() throws IOException {
          throw new IOException("mark/reset not supported");
        }

      總結(jié)

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


      網(wǎng)站欄目:通過(guò)JDK源碼學(xué)習(xí)InputStream詳解
      轉(zhuǎn)載注明:http://www.ef60e0e.cn/article/pohoge.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        宁河县| 博客| 通州区| 藁城市| 龙泉市| 普格县| 常熟市| 温宿县| 汶上县| 南木林县| 新郑市| 武鸣县| 武平县| 文化| 临洮县| 峨眉山市| 南和县| 娱乐| 铁力市| 长宁县| 无极县| 渑池县| 遂溪县| 华亭县| 迁安市| 和顺县| 延津县| 察哈| 习水县| 河间市| 普宁市| 宣恩县| 驻马店市| 潞城市| 南城县| 西充县| 刚察县| 卢氏县| 浠水县| 濉溪县| 若羌县|