天天看點

Java IO 之 InputStream源碼一、InputStream二、細解InputStream源碼的核心三、小結

inputstream是一個抽象類,即表示所有位元組輸入流實作類的基類。它的作用就是抽象地表示所有從不同資料源産生輸入的類,例如常見的fileinputstream、filterinputstream等。那些資料源呢?比如:

1) 位元組數組(不代表string類,但可以轉換) 2) string對象 3) 檔案 4) 一個其他種類的流組成的序列化 (在分布式系統中常見) 5) 管道(多線程環境中的資料源) 等等

二者,注意它是屬于位元組流部分,而不是字元流(java.io中reader\writer,下面會講到)。

源碼如下:

<a href="http://www.bysocket.com/?p=585#">?</a>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

<code>/**</code>

<code> </code><code>* 所有位元組輸入流實作類的基類</code>

<code> </code><code>*/</code>

<code>public</code> <code>abstract</code> <code>class</code> <code>sinputstream {</code>

<code>    </code><code>// 緩存區位元組數組最大值</code>

<code>    </code><code>private</code> <code>static</code> <code>final</code> <code>int</code> <code>max_skip_buffer_size =</code><code>2048</code><code>;</code>

<code>    </code><code>// 從輸入流中讀取資料的下一個位元組,以int傳回</code>

<code>    </code><code>public</code> <code>abstract</code> <code>int</code> <code>read()</code><code>throws</code> <code>ioexception;</code>

<code>    </code><code>// 從輸入流中讀取資料的一定數量位元組,并存儲在緩存數組b</code>

<code>    </code><code>public</code> <code>int</code> <code>read(</code><code>byte</code> <code>b[])</code><code>throws</code> <code>ioexception {</code>

<code>        </code><code>return</code> <code>read(b,</code><code>0</code><code>, b.length);</code>

<code>    </code><code>}</code>

<code>    </code><code>// 從輸入流中讀取資料最多len個位元組,并存儲在緩存數組b</code>

<code>    </code><code>public</code> <code>int</code> <code>read(</code><code>byte</code> <code>b[],</code><code>int</code> <code>off,</code><code>int</code> <code>len)</code><code>throws</code> <code>ioexception {</code>

<code>        </code><code>if</code> <code>(b ==</code><code>null</code><code>) {</code>

<code>            </code><code>throw</code> <code>new</code> <code>nullpointerexception();</code>

<code>        </code><code>}</code><code>else</code> <code>if</code> <code>(off &lt;</code><code>0</code> <code>|| len &lt;</code><code>0</code> <code>|| len &gt; b.length - off) {</code>

<code>            </code><code>throw</code> <code>new</code> <code>indexoutofboundsexception();</code>

<code>        </code><code>}</code><code>else</code> <code>if</code> <code>(len ==</code><code>0</code><code>) {</code>

<code>            </code><code>return</code> <code>0</code><code>;</code>

<code>        </code><code>}</code>

<code>        </code><code>int</code> <code>c = read();</code>

<code>        </code><code>if</code> <code>(c == -</code><code>1</code><code>) {</code>

<code>            </code><code>return</code> <code>-</code><code>1</code><code>;</code>

<code>        </code><code>b[off] = (</code><code>byte</code><code>)c;</code>

<code>        </code><code>int</code> <code>i =</code><code>1</code><code>;</code>

<code>        </code><code>try</code> <code>{</code>

<code>            </code><code>for</code> <code>(; i &lt; len ; i++) {</code>

<code>                </code><code>c = read();</code>

<code>                </code><code>if</code> <code>(c == -</code><code>1</code><code>) {</code>

<code>                    </code><code>break</code><code>;</code>

<code>                </code><code>}</code>

<code>                </code><code>b[off + i] = (</code><code>byte</code><code>)c;</code>

<code>            </code><code>}</code>

<code>        </code><code>}</code><code>catch</code> <code>(ioexception ee) {</code>

<code>        </code><code>return</code> <code>i;</code>

<code>    </code><code>// 跳過輸入流中資料的n個位元組</code>

<code>    </code><code>public</code> <code>long</code> <code>skip(</code><code>long</code> <code>n)</code><code>throws</code> <code>ioexception {</code>

<code>        </code><code>long</code> <code>remaining = n;</code>

<code>        </code><code>int</code> <code>nr;</code>

<code>        </code><code>if</code> <code>(n &lt;=</code><code>0</code><code>) {</code>

<code>        </code><code>int</code> <code>size = (</code><code>int</code><code>)math.min(max_skip_buffer_size, remaining);</code>

<code>        </code><code>byte</code><code>[] skipbuffer =</code><code>new</code> <code>byte</code><code>[size];</code>

<code>        </code><code>while</code> <code>(remaining &gt;</code><code>0</code><code>) {</code>

<code>            </code><code>nr = read(skipbuffer,</code><code>0</code><code>, (</code><code>int</code><code>)math.min(size, remaining));</code>

<code>            </code><code>if</code> <code>(nr &lt;</code><code>0</code><code>) {</code>

<code>                </code><code>break</code><code>;</code>

<code>            </code><code>remaining -= nr;</code>

<code>        </code><code>return</code> <code>n - remaining;</code>

<code>    </code><code>// 傳回下一個方法調用能不受阻塞地從此讀取(或者跳過)的估計位元組數</code>

<code>    </code><code>public</code> <code>int</code> <code>available()</code><code>throws</code> <code>ioexception {</code>

<code>        </code><code>return</code> <code>0</code><code>;</code>

<code>    </code><code>// 關閉此輸入流,并釋放與其關聯的所有資源</code>

<code>    </code><code>public</code> <code>void</code> <code>close()</code><code>throws</code> <code>ioexception {}</code>

<code>    </code><code>// 在此輸出流中标記目前位置</code>

<code>    </code><code>public</code> <code>synchronized</code> <code>void</code> <code>mark(</code><code>int</code> <code>readlimit) {}</code>

<code>    </code><code>// 将此流重新定位到最後一次對此輸入流調用 mark 方法時的位置。</code>

<code>    </code><code>public</code> <code>synchronized</code> <code>void</code> <code>reset()</code><code>throws</code> <code>ioexception {</code>

<code>        </code><code>throw</code> <code>new</code> <code>ioexception(</code><code>"mark/reset not supported"</code><code>);</code>

<code>    </code><code>// 測試此輸入流是否支援 mark 和 reset 方法</code>

<code>    </code><code>public</code> <code>boolean</code> <code>marksupported() {</code>

<code>        </code><code>return</code> <code>false</code><code>;</code>

<code>}</code>

其中,inputstream下面三個read方法才是核心方法:

<code>public</code> <code>abstract</code> <code>int</code> <code>read()</code>

抽象方法,沒有具體實作。因為子類必須實作此方法的一個實作。這就是輸入流的關鍵方法。

二者,可見下面兩個read()方法都調用了這個方法子類的實作來完成功能的。

<code>public</code> <code>int</code> <code>read(</code><code>byte</code> <code>b[])</code>

該方法是表示從輸入流中讀取資料的一定數量位元組,并存儲在緩存位元組數組b。其效果等同于調用了下面方法的實作:

<code>read(b,</code><code>0</code><code>, b.length)</code>

如果<code>b</code>的長度為 0,則不讀取任何位元組并傳回 <code>0</code>;否則,嘗試讀取至少 1 位元組。如果因為流位于檔案末尾而沒有可用的位元組,則傳回值 <code>-1</code>;否則,至少讀取一個位元組并将其存儲在 <code>b</code> 中。

思考:這時候,怪不得很多時候, b != –1 或者 b != eof

<code>public</code> <code>int</code> <code>read(</code><code>byte</code> <code>b[],</code><code>int</code> <code>off,</code><code>int</code> <code>len)</code>

在輸入資料可用、檢測到流末尾或者抛出異常前,此方法一直阻塞。

該方法先進行校驗,然後校驗下個位元組是否為空。如果校驗通過後,

如下代碼:

<code>int</code> <code>i =</code><code>1</code><code>;</code>

<code>try</code> <code>{</code>

<code>    </code><code>for</code> <code>(; i &lt; len ; i++) {</code>

<code>        </code><code>c = read();</code>

<code>            </code><code>break</code><code>;</code>

<code>        </code><code>b[off + i] = (</code><code>byte</code><code>)c;</code>

<code>}</code><code>catch</code> <code>(ioexception ee) {</code>

将讀取的第一個位元組存儲在元素 <code>b[off]</code> 中,下一個存儲在 <code>b[off+1]</code> 中,依次類推。讀取的位元組數最多等于 <code>len</code>。設 k 為實際讀取的位元組數;這些位元組将存儲在 <code>b[off]</code> 到<code>b[off+</code>k<code>-1]</code> 的元素中,不影響 <code>b[off+</code>k<code>]</code> 到 <code>b[off+len-1]</code> 的元素。

因為有上面兩個read的實作,是以這裡inputstream設計為抽象類。

1. inputsream 對應着 outputstream 2. 看源碼是享受人家寫代碼中流露的how