ByteArrayInputStream類


一、說明

哈哈,這是學習Java之路的第一篇博文。雖然說接觸學習Java有一段時間了,但是對流的概念一直並不是很清楚。也看了很多資料,但是感覺還是非常的抽象很難去理解。但是流又是Java中很重要的一部分,所以就決定花點時間好好弄一下。這篇文章也並非全部是我的原創文章,我瀏覽了寫的比較好的博客,將其修改添加,加上一些自己的看法,就當成自己學習的筆記。僅供學習參考。參考原文鏈接

 

二、ByteArrayInputStream類

流的概念真的是挺令人困惑的。有一本書中說: 流代表任何有能力產出數據的數據流對象,或者有能力接收數據的接收端對象開始也是不理解的,后來結合流類的jdk源碼,測試實例仔細想一下,好像是這么回事。這個流的定義好在把抽象的流定義在了對象上。
再來說一下ByteArrayInputStream類。
ByteArrayInputStream 是字節數組輸入流。它繼承於InputStream。
它包含一個內部緩沖區,該緩沖區包含從流中讀取的字節;通俗點說,它的內部緩沖區就是一個字節數組,而ByteArrayInputStream本質就是通過字節數組來實現的。
我們都知道,InputStream通過read()向外提供接口,供它們來讀取字節數據;而ByteArrayInputStream 的內部額外的定義了一個計數器,它被用來跟蹤 read() 方法要讀取的下一個字節。
 

InputStream類

InputStream類函數列表

函數 返回值 功能
public int read()  throws IOEXception

返回下一個數據字節

(返回 0255 范圍內的 int 字節值)

從輸入流中讀取數據的下一個字節
public int read(byte[] b)  throws IOEXception

 以整數形式返回實際讀取的字節數。

如果因為已經到達流末尾而不再有數據可用,

則返回 -1

從輸入流中讀取一定數量的字節,

並將其存儲在緩沖區數組 b

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

         throws IOEXception

 讀入緩沖區的總字節數;

如果因為已到達流末尾而不再有數據可用,

則返回 -1

 將輸入流中最多 len 個數據字節讀入 byte 數
public long skip(long n)  throws IOEXception 跳過的實際字節數 跳過和丟棄此輸入流中數據的 n 個字
public int available()  throws IOEXception 
             

可以不受阻塞地從此輸入流讀取

(或跳過)的估計字節數

返回此輸入流下一個方法調用

可以不受阻塞地從此輸入流讀取

(或跳過)的估計字節數

public boolean markSupported()

如果此輸入流實例支持 mark 和 reset 方法,

則返回 true;否則返回 false

測試此輸入流是否支持 markreset 方法
public void mark(int readlimit) 在此輸入流中標記當前的位置
public void reset() throws IOEXception

將此流重新定位到最后一次對此輸入流

調用 mark 方法時的位置

public void close() throws IOEXception 關閉此輸入流並釋放與該流關聯的所有系統資源

關於上表的解釋:

1.可以這樣理解read()函數里的“讀取下一個字節”,就是光標在前

2.mark()方法的參數在實現中沒有什么實際的意義。

3.InputStreamclose 方法不執行任何操作。

4.由於InputStream類是所以輸入流的父類,方法的實現也就沒有那么具體,它相當於給出了一個方法的規范,它的所以子類會按照這個規范去實現方法。也就是說,其子類方法的實現盡管不同,提供的功能卻是相同的。

5.想了解更加詳細的信息可以去查看jdk文檔,是學習java很重要的工具。jdk文檔

 

InputStream類源碼分析

由於上述給出了此類函數比較詳細的介紹,所以這里不作關於源碼太多的說明。

 1 package java.io;
 2 
 3 public abstract class InputStream implements Closeable {
 4 
 5     // 能skip的大小
 6     private static final int MAX_SKIP_BUFFER_SIZE = 2048;
 7 
 8     // 從輸入流中讀取數據的下一個字節。
 9     public abstract int read() throws IOException;
10 
11     // 將數據從輸入流讀入 byte 數組。
12     public int read(byte b[]) throws IOException {
13         return read(b, 0, b.length);
14     }
15 
16     // 將最多 len 個數據字節從此輸入流讀入 byte 數組。
17     public int read(byte b[], int off, int len) throws IOException {
18         if (b == null) {
19             throw new NullPointerException();
20         } else if (off < 0 || len < 0 || len > b.length - off) {
21             throw new IndexOutOfBoundsException();
22         } else if (len == 0) {
23             return 0;
24         }
25 
26         int c = read();
27         if (c == -1) {
28             return -1;
29         }
30         b[off] = (byte)c;
31 
32         int i = 1;
33         try {
34             for (; i < len ; i++) {
35                 c = read();
36                 if (c == -1) {
37                     break;
38                 }
39                 b[off + i] = (byte)c;
40             }
41         } catch (IOException ee) {
42         }
43         return i;
44     }
45 
46     // 跳過輸入流中的n個字節
47     public long skip(long n) throws IOException {
48 
49         long remaining = n;
50         int nr;
51 
52         if (n <= 0) {
53             return 0;
54         }
55 
56         int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);
57         byte[] skipBuffer = new byte[size];
58         while (remaining > 0) {
59             nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
60             if (nr < 0) {
61                 break;
62             }
63             remaining -= nr;
64         }
65 
66         return n - remaining;
67     }
68 
69     public int available() throws IOException {
70         return 0;
71     }
72 
73     public void close() throws IOException {}
74 
75     public synchronized void mark(int readlimit) {}
76 
77     public synchronized void reset() throws IOException {
78         throw new IOException("mark/reset not supported");
79     }
80 
81     public boolean markSupported() {
82         return false;
83     }
84 }
View Code

說明:

1.Closeable 接口表示可以關閉的數據源或目標。這個接口只有一個方法close()。

ByteArrayInputStream類

如果還是覺得上面的內容理解起來還是很抽象,很難懂。沒有關系,結合這個具體的InputStream類具體的子類ByteArrayInputStream類來看,會幫助你解開一部分困惑。計算機的學習就是這個樣子,后面的知識需要前面的知識作為鋪墊,前面的知識需要后面的知識才可以更深的理解。所以要前前后后的看一下,才可以真正的理解。

ByteArrayInputStream 包含一個內部緩沖區,該緩沖區包含從流中讀取的字節。內部計數器跟蹤 read 方法要提供的下一個字節。

關閉 ByteArrayInputStream 無效。此類中的方法在關閉此流后仍可被調用,而不會產生任何 IOException

這是jdk文檔中關於此類的描述。說明:

1.內部緩沖區指的是buf數組

2.內部計數器就是指字段pos,可以將其看成是光標

3.關閉 ByteArrayInputStream 無效指的是,關閉流的close()方法,在此類中時空方法

這里就不給出ByteArrayInputStream類的方法列表里,因為大體上和InputStream類方法列表的描述是一樣的,只是方法的實現是不同的而已。

ByteArrayInputStream類源碼分析

源碼還是很有必要看一下的可以加強對此類的理解

  1 public class ByteArrayInputStream extends InputStream {
  2 
  3     // 保存字節輸入流數據的字節數組
  4     protected byte buf[];
  5 
  6     // 下一個會被讀取的字節的索引
  7     protected int pos;
  8 
  9     // 用於標記輸入流當前位置,就是標記pos
 10     protected int mark = 0;
 11 
 12     // 字節流的長度
 13     protected int count;
 14 
 15     // 構造函數:創建一個內容為buf的字節流
 16     public ByteArrayInputStream(byte buf[]) {
 17         // 初始化“字節流對應的字節數組為buf”
 18         this.buf = buf;
 19         // 初始化“下一個要被讀取的字節索引號為0”
 20         this.pos = 0;
 21         // 初始化“字節流的長度為buf的長度”
 22         this.count = buf.length;
 23     }
 24 
 25     // 構造函數:創建一個內容為buf的字節流,並且是從offset開始讀取數據,讀取的長度最多為length
 26     public ByteArrayInputStream(byte buf[], int offset, int length) {
 27         // 初始化“字節流對應的字節數組為buf”
 28         this.buf = buf;
 29         // 初始化“下一個要被讀取的字節索引號為offset”
 30         this.pos = offset;
 31         // 初始化“字節流的長度”
 32         this.count = Math.min(offset + length, buf.length);
 33         // 初始化“標記的字節流讀取位置”
 34         this.mark = offset;
 35     }
 36 
 37     // 讀取下一個字節
 38     public synchronized int read() {
 39         return (pos < count) ? (buf[pos++] & 0xff) : -1;
 40     }
 41 
 42     // 將“字節流的數據寫入到字節數組b中”
 43     // off是“字節數組b的偏移地址”,表示從數組b的off開始寫入數據
 44     // len是“讀到b數組中的字節最大長度”
 45     public synchronized int read(byte b[], int off, int len) {
 46         if (b == null) {
 47             throw new NullPointerException();
 48         } else if (off < 0 || len < 0 || len > b.length - off) {
 49             throw new IndexOutOfBoundsException();
 50         }
 51 
 52         if (pos >= count) {
 53             return -1;
 54         }
 55 
 56         int avail = count - pos;
 57         if (len > avail) {
 58             len = avail;
 59         }
 60         if (len <= 0) {
 61             return 0;
 62         }
 63         System.arraycopy(buf, pos, b, off, len);
 64         pos += len;
 65         return len;//從字節流中成功讀出的字節數
 66     }
 67 
 68     // 跳過“字節流”中的n個字節。
 69     public synchronized long skip(long n) {
 70         long k = count - pos;
 71         if (n < k) {
 72             k = n < 0 ? 0 : n;
 73         }
 74 
 75         pos += k;
 76         return k;//成功跳過的字節數
 77     }
 78 
 79     // “能否讀取字節流的下一個字節”
 80     public synchronized int available() {
 81         return count - pos;
 82     }
 83 
 84     // 是否支持“標簽”
 85     public boolean markSupported() {
 86         return true;
 87     }
 88 
 89     // 保存當前位置。readAheadLimit在此處沒有任何實際意義
 90     public void mark(int readAheadLimit) {
 91         mark = pos;
 92     }
 93 
 94     // 重置“字節流的讀取索引”為“mark所標記的位置”
 95     public synchronized void reset() {
 96         pos = mark;
 97     }
 98 
 99     public void close() throws IOException {
100     }
101 }
View Code

 

真的是排版能力有限了。此博文僅作學習之用,歡迎指正。

 


免責聲明!

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



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