BufferedReader 介紹
BufferedReader 是緩沖字符輸入流。它繼承于Reader。
BufferedReader 的作用是為其他字符輸入流添加一些緩沖功能。
BufferedReader 函數(shù)列表
1
2
3
4
5
6
7
8
9
10
11
|
BufferedReader(Reader in) BufferedReader(Reader in, int size) void close() void mark( int markLimit) boolean markSupported() int read() int read( char [] buffer, int offset, int length) String readLine() boolean ready() void reset() long skip( long charCount) |
BufferedReader 源碼分析(基于jdk1.7.40)
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
|
package java.io; public class BufferedReader extends Reader { private Reader in; // 字符緩沖區(qū) private char cb[]; // nChars 是cb緩沖區(qū)中字符的總的個(gè)數(shù) // nextChar 是下一個(gè)要讀取的字符在cb緩沖區(qū)中的位置 private int nChars, nextChar; // 表示“標(biāo)記無(wú)效”。它與UNMARKED的區(qū)別是: // (01) UNMARKED 是壓根就沒(méi)有設(shè)置過(guò)標(biāo)記。 // (02) 而INVALIDATED是設(shè)置了標(biāo)記,但是被標(biāo)記位置太長(zhǎng),導(dǎo)致標(biāo)記無(wú)效! private static final int INVALIDATED = - 2 ; // 表示沒(méi)有設(shè)置“標(biāo)記” private static final int UNMARKED = - 1 ; // “標(biāo)記” private int markedChar = UNMARKED; // “標(biāo)記”能標(biāo)記位置的最大長(zhǎng)度 private int readAheadLimit = 0 ; /* Valid only when markedChar > 0 */ // skipLF(即skip Line Feed)是“是否忽略換行符”標(biāo)記 private boolean skipLF = false; // 設(shè)置“標(biāo)記”時(shí),保存的skipLF的值 private boolean markedSkipLF = false; // 默認(rèn)字符緩沖區(qū)大小 private static int defaultCharBufferSize = 8192; // 默認(rèn)每一行的字符個(gè)數(shù) private static int defaultExpectedLineLength = 80; // 創(chuàng)建“Reader”對(duì)應(yīng)的BufferedReader對(duì)象,sz是BufferedReader的緩沖區(qū)大小 public BufferedReader(Reader in, int sz) { super(in); if (sz <= 0) throw new IllegalArgumentException("Buffer size <= 0"); this.in = in; cb = new char[sz]; nextChar = nChars = 0; } // 創(chuàng)建“Reader”對(duì)應(yīng)的BufferedReader對(duì)象,默認(rèn)的BufferedReader緩沖區(qū)大小是8k public BufferedReader(Reader in) { this(in, defaultCharBufferSize); } // 確保“BufferedReader”是打開(kāi)狀態(tài) private void ensureOpen() throws IOException { if (in == null) throw new IOException("Stream closed"); } // 填充緩沖區(qū)函數(shù)。有以下兩種情況被調(diào)用: // (01) 緩沖區(qū)沒(méi)有數(shù)據(jù)時(shí),通過(guò)fill()可以向緩沖區(qū)填充數(shù)據(jù)。 // (02) 緩沖區(qū)數(shù)據(jù)被讀完,需更新時(shí),通過(guò)fill()可以更新緩沖區(qū)的數(shù)據(jù)。 private void fill() throws IOException { // dst表示“cb中填充數(shù)據(jù)的起始位置”。 int dst; if (markedChar <= UNMARKED) { // 沒(méi)有標(biāo)記的情況,則設(shè)dst=0。 dst = 0; } else { // delta表示“當(dāng)前標(biāo)記的長(zhǎng)度”,它等于“下一個(gè)被讀取字符的位置”減去“標(biāo)記的位置”的差值; int delta = nextChar - markedChar; if (delta >= readAheadLimit) { // 若“當(dāng)前標(biāo)記的長(zhǎng)度”超過(guò)了“標(biāo)記上限(readAheadLimit)”, // 則丟棄標(biāo)記! markedChar = INVALIDATED; readAheadLimit = 0; dst = 0; } else { if (readAheadLimit <= cb.length) { // 若“當(dāng)前標(biāo)記的長(zhǎng)度”沒(méi)有超過(guò)了“標(biāo)記上限(readAheadLimit)”, // 并且“標(biāo)記上限(readAheadLimit)”小于/等于“緩沖的長(zhǎng)度”; // 則先將“下一個(gè)要被讀取的位置,距離我們標(biāo)記的置符的距離”間的字符保存到cb中。 System.arraycopy(cb, markedChar, cb, 0, delta); markedChar = 0; dst = delta; } else { // 若“當(dāng)前標(biāo)記的長(zhǎng)度”沒(méi)有超過(guò)了“標(biāo)記上限(readAheadLimit)”, // 并且“標(biāo)記上限(readAheadLimit)”大于“緩沖的長(zhǎng)度”; // 則重新設(shè)置緩沖區(qū)大小,并將“下一個(gè)要被讀取的位置,距離我們標(biāo)記的置符的距離”間的字符保存到cb中。 char ncb[] = new char[readAheadLimit]; System.arraycopy(cb, markedChar, ncb, 0, delta); cb = ncb; markedChar = 0; dst = delta; } // 更新nextChar和nChars nextChar = nChars = delta; } } int n; do { // 從“in”中讀取數(shù)據(jù),并存儲(chǔ)到字符數(shù)組cb中; // 從cb的dst位置開(kāi)始存儲(chǔ),讀取的字符個(gè)數(shù)是cb.length - dst // n是實(shí)際讀取的字符個(gè)數(shù);若n==0(即一個(gè)也沒(méi)讀到),則繼續(xù)讀?。?/code> n = in.read(cb, dst, cb.length - dst); } while (n == 0); // 如果從“in”中讀到了數(shù)據(jù),則設(shè)置nChars(cb中字符的數(shù)目)=dst+n, // 并且nextChar(下一個(gè)被讀取的字符的位置)=dst。 if (n > 0) { nChars = dst + n; nextChar = dst; } } // 從BufferedReader中讀取一個(gè)字符,該字符以int的方式返回 public int read() throws IOException { synchronized (lock) { ensureOpen(); for (;;) { // 若“緩沖區(qū)的數(shù)據(jù)已經(jīng)被讀完”, // 則先通過(guò)fill()更新緩沖區(qū)數(shù)據(jù) if (nextChar >= nChars) { fill(); if (nextChar >= nChars) return -1; } // 若要“忽略換行符”, // 則對(duì)下一個(gè)字符是否是換行符進(jìn)行處理。 if (skipLF) { skipLF = false; if (cb[nextChar] == '\n') { nextChar++; continue; } } // 返回下一個(gè)字符 return cb[nextChar++]; } } } // 將緩沖區(qū)中的數(shù)據(jù)寫(xiě)入到數(shù)組cbuf中。off是數(shù)組cbuf中的寫(xiě)入起始位置,len是寫(xiě)入長(zhǎng)度 private int read(char[] cbuf, int off, int len) throws IOException { // 若“緩沖區(qū)的數(shù)據(jù)已經(jīng)被讀完”,則更新緩沖區(qū)數(shù)據(jù)。 if (nextChar >= nChars) { if (len >= cb.length && markedChar <= UNMARKED && !skipLF) { return in.read(cbuf, off, len); } fill(); } // 若更新數(shù)據(jù)之后,沒(méi)有任何變化;則退出。 if (nextChar >= nChars) return -; // 若要“忽略換行符”,則進(jìn)行相應(yīng)處理 if (skipLF) { skipLF = false; if (cb[nextChar] == '\n') { nextChar++; if (nextChar >= nChars) fill(); if (nextChar >= nChars) return -1; } } // 拷貝字符操作 int n = Math.min(len, nChars - nextChar); System.arraycopy(cb, nextChar, cbuf, off, n); nextChar += n; return n; } // 對(duì)read()的封裝,添加了“同步處理”和“阻塞式讀取”等功能 public int read(char cbuf[], int off, int len) throws IOException { synchronized (lock) { ensureOpen(); if ((off < 0) || (off > cbuf.length) || (len < 0) || ((off + len) > cbuf.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } int n = read1(cbuf, off, len); if (n <= 0) return n; while ((n < len) && in.ready()) { int n1 = read1(cbuf, off + n, len - n); if (n1 <= 0) break; n += n1; } return n; } } // 讀取一行數(shù)據(jù)。ignoreLF是“是否忽略換行符” String readLine(boolean ignoreLF) throws IOException { StringBuffer s = null; int startChar; synchronized (lock) { ensureOpen(); boolean omitLF = ignoreLF || skipLF; bufferLoop: for (;;) { if (nextChar >= nChars) fill(); if (nextChar >= nChars) { /* EOF */ if (s != null && s.length() > 0) return s.toString(); else return null; } boolean eol = false; char c = 0; int i; /* Skip a leftover '\n', if necessary */ if (omitLF && (cb[nextChar] == '\n')) nextChar++; skipLF = false; omitLF = false; charLoop: for (i = nextChar; i < nChars; i++) { c = cb[i]; if ((c == '\n') || (c == '\r')) { eol = true; break charLoop; } } startChar = nextChar; nextChar = i; if (eol) { String str; if (s == null) { str = new String(cb, startChar, i - startChar); } else { s.append(cb, startChar, i - startChar); str = s.toString(); } nextChar++; if (c == '\r') { skipLF = true; } return str; } if (s == null) s = new StringBuffer(defaultExpectedLineLength); s.append(cb, startChar, i - startChar); } } } // 讀取一行數(shù)據(jù)。不忽略換行符 public String readLine() throws IOException { return readLine(false); } // 跳過(guò)n個(gè)字符 public long skip(long n) throws IOException { if (n < 0L) { throw new IllegalArgumentException("skip value is negative"); } synchronized (lock) { ensureOpen(); long r = n; while (r > 0) { if (nextChar >= nChars) fill(); if (nextChar >= nChars) /* EOF */ break ; if (skipLF) { skipLF = false ; if (cb[nextChar] == '\n' ) { nextChar++; } } long d = nChars - nextChar; if (r <= d) { nextChar += r; r = 0 ; break ; } else { r -= d; nextChar = nChars; } } return n - r; } } // “下一個(gè)字符”是否可讀 public boolean ready() throws IOException { synchronized (lock) { ensureOpen(); // 若忽略換行符為true; // 則判斷下一個(gè)符號(hào)是否是換行符,若是的話(huà),則忽略 if (skipLF) { if (nextChar >= nChars && in.ready()) { fill(); } if (nextChar < nChars) { if (cb[nextChar] == '\n' ) nextChar++; skipLF = false ; } } return (nextChar < nChars) || in.ready(); } } // 始終返回true。因?yàn)锽ufferedReader支持mark(), reset() public boolean markSupported() { return true ; } // 標(biāo)記當(dāng)前BufferedReader的下一個(gè)要讀取位置。關(guān)于readAheadLimit的作用,參考后面的說(shuō)明。 public void mark( int readAheadLimit) throws IOException { if (readAheadLimit < 0 ) { throw new IllegalArgumentException( "Read-ahead limit < 0" ); } synchronized (lock) { ensureOpen(); // 設(shè)置readAheadLimit this .readAheadLimit = readAheadLimit; // 保存下一個(gè)要讀取的位置 markedChar = nextChar; // 保存“是否忽略換行符”標(biāo)記 markedSkipLF = skipLF; } } // 重置BufferedReader的下一個(gè)要讀取位置, // 將其還原到mark()中所保存的位置。 public void reset() throws IOException { synchronized (lock) { ensureOpen(); if (markedChar < 0 ) throw new IOException((markedChar == INVALIDATED) ? "Mark invalid" : "Stream not marked" ); nextChar = markedChar; skipLF = markedSkipLF; } } public void close() throws IOException { synchronized (lock) { if (in == null ) return ; in.close(); in = null ; cb = null ; } } } |
說(shuō)明:
要想讀懂BufferReader的源碼,就要先理解它的思想。BufferReader的作用是為其它Reader提供緩沖功能。創(chuàng)建BufferReader時(shí),我們會(huì)通過(guò)它的構(gòu)造函數(shù)指定某個(gè)Reader為參數(shù)。BufferReader會(huì)將該Reader中的數(shù)據(jù)分批讀取,每次讀取一部分到緩沖中;操作完緩沖中的這部分?jǐn)?shù)據(jù)之后,再?gòu)腞eader中讀取下一部分的數(shù)據(jù)。
為什么需要緩沖呢?原因很簡(jiǎn)單,效率問(wèn)題!緩沖中的數(shù)據(jù)實(shí)際上是保存在內(nèi)存中,而原始數(shù)據(jù)可能是保存在硬盤(pán)或NandFlash中;而我們知道,從內(nèi)存中讀取數(shù)據(jù)的速度比從硬盤(pán)讀取數(shù)據(jù)的速度至少快10倍以上。
那干嘛不干脆一次性將全部數(shù)據(jù)都讀取到緩沖中呢?第一,讀取全部的數(shù)據(jù)所需要的時(shí)間可能會(huì)很長(zhǎng)。第二,內(nèi)存價(jià)格很貴,容量不想硬盤(pán)那么大。
下面,我就BufferReader中最重要的函數(shù)fill()進(jìn)行說(shuō)明。其它的函數(shù)很容易理解,我就不詳細(xì)介紹了,大家可以參考源碼中的注釋進(jìn)行理解。我們先看看fill()的源碼:
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
|
private void fill() throws IOException { int dst; if (markedChar <= UNMARKED) { /* No mark */ dst = 0; } else { /* Marked */ int delta = nextChar - markedChar; if (delta >= readAheadLimit) { /* Gone past read-ahead limit: Invalidate mark */ markedChar = INVALIDATED; readAheadLimit = 0; dst = 0; } else { if (readAheadLimit <= cb.length) { /* Shuffle in the current buffer */ System.arraycopy(cb, markedChar, cb, 0, delta); markedChar = 0; dst = delta; } else { /* Reallocate buffer to accommodate read-ahead limit */ char ncb[] = new char [readAheadLimit]; System.arraycopy(cb, markedChar, ncb, 0 , delta); cb = ncb; markedChar = 0 ; dst = delta; } nextChar = nChars = delta; } } int n; do { n = in.read(cb, dst, cb.length - dst); } while (n == 0 ); if (n > 0 ) { nChars = dst + n; nextChar = dst; } } |
根據(jù)fill()中的if...else...,我將fill()分為4種情況進(jìn)行說(shuō)明。
情況1:讀取完緩沖區(qū)的數(shù)據(jù),并且緩沖區(qū)沒(méi)有被標(biāo)記
執(zhí)行流程如下,
(01) 其它函數(shù)調(diào)用 fill(),來(lái)更新緩沖區(qū)的數(shù)據(jù)
(02) fill() 執(zhí)行代碼 if (markedChar <= UNMARKED) { ... }
為了方便分析,我們將這種情況下fill()執(zhí)行的操作等價(jià)于以下代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
private void fill() throws IOException { int dst; if (markedChar <= UNMARKED) { /* No mark */ dst = 0 ; } int n; do { n = in.read(cb, dst, cb.length - dst); } while (n == 0 ); if (n > 0 ) { nChars = dst + n; nextChar = dst; } } |
說(shuō)明:
這種情況發(fā)生的情況是 — — Reader中有很長(zhǎng)的數(shù)據(jù),我們每次從中讀取一部分?jǐn)?shù)據(jù)到緩沖中進(jìn)行操作。每次當(dāng)我們讀取完緩沖中的數(shù)據(jù)之后,并且此時(shí)BufferedReader沒(méi)有被標(biāo)記;那么,就接著從Reader(BufferReader提供緩沖功能的Reader)中讀取下一部分的數(shù)據(jù)到緩沖中。
其中,判斷是否讀完緩沖區(qū)中的數(shù)據(jù),是通過(guò)“比較nextChar和nChars之間大小”來(lái)判斷的。其中,nChars 是緩沖區(qū)中字符的總的個(gè)數(shù),而 nextChar 是緩沖區(qū)中下一個(gè)要讀取的字符的位置。
判斷BufferedReader有沒(méi)有被標(biāo)記,是通過(guò)“markedChar”來(lái)判斷的。
理解這個(gè)思想之后,我們?cè)賹?duì)這種情況下的fill()的代碼進(jìn)行分析,就特別容易理解了。
(01) if (markedChar <= UNMARKED) 它的作用是判斷“BufferedReader是否被標(biāo)記”。若被標(biāo)記,則dst=0。
(02) in.read(cb, dst, cb.length - dst) 等價(jià)于 in.read(cb, 0, cb.length),意思是從Reader對(duì)象in中讀取cb.length個(gè)數(shù)據(jù),并存儲(chǔ)到緩沖區(qū)cb中,而且從緩沖區(qū)cb的位置0開(kāi)始存儲(chǔ)。該函數(shù)返回值等于n,也就是n表示實(shí)際讀取的字符個(gè)數(shù)。若n=0(即沒(méi)有讀取到數(shù)據(jù)),則繼續(xù)讀取,直到讀到數(shù)據(jù)為止。
(03) nChars=dst+n 等價(jià)于 nChars=n;意味著,更新緩沖區(qū)數(shù)據(jù)cb之后,設(shè)置nChars(緩沖區(qū)的數(shù)據(jù)個(gè)數(shù))為n。
(04) nextChar=dst 等價(jià)于 nextChar=0;意味著,更新緩沖區(qū)數(shù)據(jù)cb之后,設(shè)置nextChar(緩沖區(qū)中下一個(gè)會(huì)被讀取的字符的索引值)為0。
情況2:讀取完緩沖區(qū)的數(shù)據(jù),緩沖區(qū)的標(biāo)記位置>0,并且“當(dāng)前標(biāo)記的長(zhǎng)度”超過(guò)“標(biāo)記上限(readAheadLimit)”
執(zhí)行流程如下,
(01) 其它函數(shù)調(diào)用 fill(),來(lái)更新緩沖區(qū)的數(shù)據(jù)
(02) fill() 執(zhí)行代碼 if (delta >= readAheadLimit) { ... }
為了方便分析,我們將這種情況下fill()執(zhí)行的操作等價(jià)于以下代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
private void fill() throws IOException { int dst; if (markedChar > UNMARKED) { int delta = nextChar - markedChar; if (delta >= readAheadLimit) { markedChar = INVALIDATED; readAheadLimit = 0 ; dst = 0 ; } } int n; do { n = in.read(cb, dst, cb.length - dst); } while (n == 0 ); if (n > 0 ) { nChars = dst + n; nextChar = dst; } } |
說(shuō)明:
這種情況發(fā)生的情況是 — — BufferedReader中有很長(zhǎng)的數(shù)據(jù),我們每次從中讀取一部分?jǐn)?shù)據(jù)到緩沖區(qū)中進(jìn)行操作。當(dāng)我們讀取完緩沖區(qū)中的數(shù)據(jù)之后,并且此時(shí),BufferedReader存在標(biāo)記時(shí),同時(shí),“當(dāng)前標(biāo)記的長(zhǎng)度”大于“標(biāo)記上限”;那么,就發(fā)生情況2。此時(shí),我們會(huì)丟棄“標(biāo)記”并更新緩沖區(qū)。
(01) delta = nextChar - markedChar;其中,delta就是“當(dāng)前標(biāo)記的長(zhǎng)度”,它是“下一個(gè)被讀取字符的位置”減去“被標(biāo)記的位置”的差值。
(02) if (delta >= readAheadLimit);其中,當(dāng)delta >= readAheadLimit,就意味著,“當(dāng)前標(biāo)記的長(zhǎng)度”>=“標(biāo)記上限”。為什么要有標(biāo)記上限,即readAheadLimit的值到底有何意義呢?
我們標(biāo)記一個(gè)位置之后,更新緩沖區(qū)的時(shí)候,被標(biāo)記的位置會(huì)被保存;當(dāng)我們不停的更新緩沖區(qū)的時(shí)候,被標(biāo)記的位置會(huì)被不停的放大。然后內(nèi)存的容量是有效的,我們不可能不限制長(zhǎng)度的存儲(chǔ)標(biāo)記。所以,需要readAheadLimit來(lái)限制標(biāo)記長(zhǎng)度!
(03) in.read(cb, dst, cb.length - dst) 等價(jià)于 in.read(cb, 0, cb.length),意思是從Reader對(duì)象in中讀取cb.length個(gè)數(shù)據(jù),并存儲(chǔ)到緩沖區(qū)cb中,而且從緩沖區(qū)cb的位置0開(kāi)始存儲(chǔ)。該函數(shù)返回值等于n,也就是n表示實(shí)際讀取的字符個(gè)數(shù)。若n=0(即沒(méi)有讀取到數(shù)據(jù)),則繼續(xù)讀取,直到讀到數(shù)據(jù)為止。
(04) nChars=dst+n 等價(jià)于 nChars=n;意味著,更新緩沖區(qū)數(shù)據(jù)cb之后,設(shè)置nChars(緩沖區(qū)的數(shù)據(jù)個(gè)數(shù))為n。
(05) nextChar=dst 等價(jià)于 nextChar=0;意味著,更新緩沖區(qū)數(shù)據(jù)cb之后,設(shè)置nextChar(緩沖區(qū)中下一個(gè)會(huì)被讀取的字符的索引值)為0。
情況3:讀取完緩沖區(qū)的數(shù)據(jù),緩沖區(qū)的標(biāo)記位置>0,“當(dāng)前標(biāo)記的長(zhǎng)度”沒(méi)超過(guò)“標(biāo)記上限(readAheadLimit)”,并且“標(biāo)記上限(readAheadLimit)”小于/等于“緩沖的長(zhǎng)度”;
執(zhí)行流程如下,
(01) 其它函數(shù)調(diào)用 fill(),來(lái)更新緩沖區(qū)的數(shù)據(jù)
(02) fill() 執(zhí)行代碼 if (readAheadLimit <= cb.length) { ... }
為了方便分析,我們將這種情況下fill()執(zhí)行的操作等價(jià)于以下代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
private void fill() throws IOException { int dst; if (markedChar > UNMARKED) { int delta = nextChar - markedChar; if ((delta < readAheadLimit) && (readAheadLimit <= cb.length) ) { System.arraycopy(cb, markedChar, cb, 0 , delta); markedChar = 0 ; dst = delta; nextChar = nChars = delta; } } int n; do { n = in.read(cb, dst, cb.length - dst); } while (n == 0 ); if (n > 0 ) { nChars = dst + n; nextChar = dst; } } |
說(shuō)明:
這種情況發(fā)生的情況是 — — BufferedReader中有很長(zhǎng)的數(shù)據(jù),我們每次從中讀取一部分?jǐn)?shù)據(jù)到緩沖區(qū)中進(jìn)行操作。當(dāng)我們讀取完緩沖區(qū)中的數(shù)據(jù)之后,并且此時(shí),BufferedReader存在標(biāo)記時(shí),同時(shí),“當(dāng)前標(biāo)記的長(zhǎng)度”小于“標(biāo)記上限”,并且“標(biāo)記上限”小于/等于“緩沖區(qū)長(zhǎng)度”;那么,就發(fā)生情況3。此時(shí),我們保留“被標(biāo)記的位置”(即,保留被標(biāo)記位置開(kāi)始的數(shù)據(jù)),并更新緩沖區(qū)(將新增的數(shù)據(jù),追加到保留的數(shù)據(jù)之后)。
情況4:讀取完緩沖區(qū)的數(shù)據(jù),緩沖區(qū)的標(biāo)記位置>0,“當(dāng)前標(biāo)記的長(zhǎng)度”沒(méi)超過(guò)“標(biāo)記上限(readAheadLimit)”,并且“標(biāo)記上限(readAheadLimit)”大于“緩沖的長(zhǎng)度”;
執(zhí)行流程如下,
(01) 其它函數(shù)調(diào)用 fill(),來(lái)更新緩沖區(qū)的數(shù)據(jù)
(02) fill() 執(zhí)行代碼 else { char ncb[] = new char[readAheadLimit]; ... }
為了方便分析,我們將這種情況下fill()執(zhí)行的操作等價(jià)于以下代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
private void fill() throws IOException { int dst; if (markedChar > UNMARKED) { int delta = nextChar - markedChar; if ((delta < readAheadLimit) && (readAheadLimit > cb.length) ) { char ncb[] = new char [readAheadLimit]; System.arraycopy(cb, markedChar, ncb, 0 , delta); cb = ncb; markedChar = 0 ; dst = delta; nextChar = nChars = delta; } } int n; do { n = in.read(cb, dst, cb.length - dst); } while (n == ); if (n > ) { nChars = dst + n; nextChar = dst; } } |
說(shuō)明:
這種情況發(fā)生的情況是 — — BufferedReader中有很長(zhǎng)的數(shù)據(jù),我們每次從中讀取一部分?jǐn)?shù)據(jù)到緩沖區(qū)中進(jìn)行操作。當(dāng)我們讀取完緩沖區(qū)中的數(shù)據(jù)之后,并且此時(shí),BufferedReader存在標(biāo)記時(shí),同時(shí),“當(dāng)前標(biāo)記的長(zhǎng)度”小于“標(biāo)記上限”,并且“標(biāo)記上限”大于“緩沖區(qū)長(zhǎng)度”;那么,就發(fā)生情況4。此時(shí),我們要先更新緩沖區(qū)的大小,然后再保留“被標(biāo)記的位置”(即,保留被標(biāo)記位置開(kāi)始的數(shù)據(jù)),并更新緩沖區(qū)數(shù)據(jù)(將新增的數(shù)據(jù),追加到保留的數(shù)據(jù)之后)。
示例代碼
關(guān)于BufferedReader中API的詳細(xì)用法,參考示例代碼(BufferedReaderTest.java):
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
|
import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; import java.io.FileReader; import java.io.IOException; import java.io.FileNotFoundException; import java.lang.SecurityException; /** * BufferedReader 測(cè)試程序 * * */ public class BufferedReaderTest { private static final int LEN = 5 ; public static void main(String[] args) { testBufferedReader() ; } /** * BufferedReader的API測(cè)試函數(shù) */ private static void testBufferedReader() { // 創(chuàng)建BufferedReader字符流,內(nèi)容是ArrayLetters數(shù)組 try { File file = new File( "bufferedreader.txt" ); BufferedReader in = new BufferedReader( new FileReader(file)); // 從字符流中讀取5個(gè)字符。“abcde” for ( int i= 0 ; i<LEN; i++) { // 若能繼續(xù)讀取下一個(gè)字符,則讀取下一個(gè)字符 if (in.ready()) { // 讀取“字符流的下一個(gè)字符” int tmp = in.read(); System.out.printf( "%d : %c\n" , i, tmp); } } // 若“該字符流”不支持標(biāo)記功能,則直接退出 if (!in.markSupported()) { System.out.println( "make not supported!" ); return ; } // 標(biāo)記“當(dāng)前索引位置”,即標(biāo)記第6個(gè)位置的元素--“f” // 1024對(duì)應(yīng)marklimit in.mark( 1024 ); // 跳過(guò)22個(gè)字符。 in.skip( 22 ); // 讀取5個(gè)字符 char [] buf = new char [LEN]; in.read(buf, 0 , LEN); System.out.printf( "buf=%s\n" , String.valueOf(buf)); // 讀取該行剩余的數(shù)據(jù) System.out.printf( "readLine=%s\n" , in.readLine()); // 重置“輸入流的索引”為mark()所標(biāo)記的位置,即重置到“f”處。 in.reset(); // 從“重置后的字符流”中讀取5個(gè)字符到buf中。即讀取“fghij” in.read(buf, , LEN); System.out.printf( "buf=%s\n" , String.valueOf(buf)); in.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } |
程序中讀取的bufferedreader.txt的內(nèi)容如下:
1
2
3
|
abcdefghijklmnopqrstuvwxyz 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ |
運(yùn)行結(jié)果:
1
2
3
4
5
6
7
8
|
0 : a 1 : b 2 : c 3 : d 4 : e buf= 01234 readLine= 56789 buf=fghij |
以上所述是小編給大家介紹的Java 中的 BufferedReader 介紹_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)服務(wù)器之家網(wǎng)站的支持!