java bufferedread_java io系列23之 BufferedReader(字符缓冲输入流)

1 packagejava.io;2

3 public class BufferedReader extendsReader {4

5 privateReader in;6

7 //字符缓冲区

8 private charcb[];9 //nChars 是cb缓冲区中字符的总的个数10 //nextChar 是下一个要读取的字符在cb缓冲区中的位置

11 private intnChars, nextChar;12

13 //表示“标记无效”。它与UNMARKED的区别是:14 //(01) UNMARKED 是压根就没有设置过标记。15 //(02) 而INVALIDATED是设置了标记,但是被标记位置太长,导致标记无效!

16 private static final int INVALIDATED = -2;17 //表示没有设置“标记”

18 private static final int UNMARKED = -1;19 //“标记”

20 private int markedChar =UNMARKED;21 //“标记”能标记位置的最大长度

22 private int readAheadLimit = 0; /*Valid only when markedChar > 0*/

23

24 //skipLF(即skip Line Feed)是“是否忽略换行符”标记

25 private boolean skipLF = false;26

27 //设置“标记”时,保存的skipLF的值

28 private boolean markedSkipLF = false;29

30 //默认字符缓冲区大小

31 private static int defaultCharBufferSize = 8192;32 //默认每一行的字符个数

33 private static int defaultExpectedLineLength = 80;34

35 //创建“Reader”对应的BufferedReader对象,sz是BufferedReader的缓冲区大小

36 public BufferedReader(Reader in, intsz) {37 super(in);38 if (sz <= 0)39 throw new IllegalArgumentException("Buffer size <= 0");40 this.in =in;41 cb = new char[sz];42 nextChar = nChars = 0;43 }44

45 //创建“Reader”对应的BufferedReader对象,默认的BufferedReader缓冲区大小是8k

46 publicBufferedReader(Reader in) {47 this(in, defaultCharBufferSize);48 }49

50 //确保“BufferedReader”是打开状态

51 private void ensureOpen() throwsIOException {52 if (in == null)53 throw new IOException("Stream closed");54 }55

56 //填充缓冲区函数。有以下两种情况被调用:57 //(01) 缓冲区没有数据时,通过fill()可以向缓冲区填充数据。58 //(02) 缓冲区数据被读完,需更新时,通过fill()可以更新缓冲区的数据。

59 private void fill() throwsIOException {60 //dst表示“cb中填充数据的起始位置”。

61 intdst;62 if (markedChar <=UNMARKED) {63 //没有标记的情况,则设dst=0。

64 dst = 0;65 } else{66 //delta表示“当前标记的长度”,它等于“下一个被读取字符的位置”减去“标记的位置”的差值;

67 int delta = nextChar -markedChar;68 if (delta >=readAheadLimit) {69 //若“当前标记的长度”超过了“标记上限(readAheadLimit)”,70 //则丢弃标记!

71 markedChar =INVALIDATED;72 readAheadLimit = 0;73 dst = 0;74 } else{75 if (readAheadLimit <=cb.length) {76 //若“当前标记的长度”没有超过了“标记上限(readAheadLimit)”,77 //并且“标记上限(readAheadLimit)”小于/等于“缓冲的长度”;78 //则先将“下一个要被读取的位置,距离我们标记的置符的距离”间的字符保存到cb中。

79 System.arraycopy(cb, markedChar, cb, 0, delta);80 markedChar = 0;81 dst =delta;82 } else{83 //若“当前标记的长度”没有超过了“标记上限(readAheadLimit)”,84 //并且“标记上限(readAheadLimit)”大于“缓冲的长度”;85 //则重新设置缓冲区大小,并将“下一个要被读取的位置,距离我们标记的置符的距离”间的字符保存到cb中。

86 char ncb[] = new char[readAheadLimit];87 System.arraycopy(cb, markedChar, ncb, 0, delta);88 cb =ncb;89 markedChar = 0;90 dst =delta;91 }92 //更新nextChar和nChars

93 nextChar = nChars =delta;94 }95 }96

97 intn;98 do{99 //从“in”中读取数据,并存储到字符数组cb中;100 //从cb的dst位置开始存储,读取的字符个数是cb.length - dst101 //n是实际读取的字符个数;若n==0(即一个也没读到),则继续读取!

102 n = in.read(cb, dst, cb.length -dst);103 } while (n == 0);104

105 //如果从“in”中读到了数据,则设置nChars(cb中字符的数目)=dst+n,106 //并且nextChar(下一个被读取的字符的位置)=dst。

107 if (n > 0) {108 nChars = dst +n;109 nextChar =dst;110 }111 }112

113 //从BufferedReader中读取一个字符,该字符以int的方式返回

114 public int read() throwsIOException {115 synchronized(lock) {116 ensureOpen();117 for(;;) {118 //若“缓冲区的数据已经被读完”,119 //则先通过fill()更新缓冲区数据

120 if (nextChar >=nChars) {121 fill();122 if (nextChar >=nChars)123 return -1;124 }125 //若要“忽略换行符”,126 //则对下一个字符是否是换行符进行处理。

127 if(skipLF) {128 skipLF = false;129 if (cb[nextChar] == '\n') {130 nextChar++;131 continue;132 }133 }134 //返回下一个字符

135 return cb[nextChar++];136 }137 }138 }139

140 //将缓冲区中的数据写入到数组cbuf中。off是数组cbuf中的写入起始位置,len是写入长度

141 private int read1(char[] cbuf, int off, int len) throwsIOException {142 //若“缓冲区的数据已经被读完”,则更新缓冲区数据。

143 if (nextChar >=nChars) {144 if (len >= cb.length && markedChar <= UNMARKED && !skipLF) {145 returnin.read(cbuf, off, len);146 }147 fill();148 }149 //若更新数据之后,没有任何变化;则退出。

150 if (nextChar >= nChars) return -1;151 //若要“忽略换行符”,则进行相应处理

152 if(skipLF) {153 skipLF = false;154 if (cb[nextChar] == '\n') {155 nextChar++;156 if (nextChar >=nChars)157 fill();158 if (nextChar >=nChars)159 return -1;160 }161 }162 //拷贝字符操作

163 int n = Math.min(len, nChars -nextChar);164 System.arraycopy(cb, nextChar, cbuf, off, n);165 nextChar +=n;166 returnn;167 }168

169 //对read1()的封装,添加了“同步处理”和“阻塞式读取”等功能

170 public int read(char cbuf[], int off, int len) throwsIOException {171 synchronized(lock) {172 ensureOpen();173 if ((off < 0) || (off > cbuf.length) || (len < 0) ||

174 ((off + len) > cbuf.length) || ((off + len) < 0)) {175 throw newIndexOutOfBoundsException();176 } else if (len == 0) {177 return 0;178 }179

180 int n =read1(cbuf, off, len);181 if (n <= 0) returnn;182 while ((n < len) &&in.ready()) {183 int n1 = read1(cbuf, off + n, len -n);184 if (n1 <= 0) break;185 n +=n1;186 }187 returnn;188 }189 }190

191 //读取一行数据。ignoreLF是“是否忽略换行符”

192 String readLine(boolean ignoreLF) throwsIOException {193 StringBuffer s = null;194 intstartChar;195

196 synchronized(lock) {197 ensureOpen();198 boolean omitLF = ignoreLF ||skipLF;199

200 bufferLoop:201 for(;;) {202

203 if (nextChar >=nChars)204 fill();205 if (nextChar >= nChars) { /*EOF*/

206 if (s != null && s.length() > 0)207 returns.toString();208 else

209 return null;210 }211 boolean eol = false;212 char c = 0;213 inti;214

215 /*Skip a leftover '\n', if necessary*/

216 if (omitLF && (cb[nextChar] == '\n'))217 nextChar++;218 skipLF = false;219 omitLF = false;220

221 charLoop:222 for (i = nextChar; i < nChars; i++) {223 c =cb[i];224 if ((c == '\n') || (c == '\r')) {225 eol = true;226 breakcharLoop;227 }228 }229

230 startChar =nextChar;231 nextChar =i;232

233 if(eol) {234 String str;235 if (s == null) {236 str = new String(cb, startChar, i -startChar);237 } else{238 s.append(cb, startChar, i -startChar);239 str =s.toString();240 }241 nextChar++;242 if (c == '\r') {243 skipLF = true;244 }245 returnstr;246 }247

248 if (s == null)249 s = newStringBuffer(defaultExpectedLineLength);250 s.append(cb, startChar, i -startChar);251 }252 }253 }254

255 //读取一行数据。不忽略换行符

256 public String readLine() throwsIOException {257 return readLine(false);258 }259

260 //跳过n个字符

261 public long skip(long n) throwsIOException {262 if (n < 0L) {263 throw new IllegalArgumentException("skip value is negative");264 }265 synchronized(lock) {266 ensureOpen();267 long r =n;268 while (r > 0) {269 if (nextChar >=nChars)270 fill();271 if (nextChar >= nChars) /*EOF*/

272 break;273 if(skipLF) {274 skipLF = false;275 if (cb[nextChar] == '\n') {276 nextChar++;277 }278 }279 long d = nChars -nextChar;280 if (r <=d) {281 nextChar +=r;282 r = 0;283 break;284 }285 else{286 r -=d;287 nextChar =nChars;288 }289 }290 return n -r;291 }292 }293

294 //“下一个字符”是否可读

295 public boolean ready() throwsIOException {296 synchronized(lock) {297 ensureOpen();298

299 //若忽略换行符为true;300 //则判断下一个符号是否是换行符,若是的话,则忽略

301 if(skipLF) {302 if (nextChar >= nChars &&in.ready()) {303 fill();304 }305 if (nextChar

315 //始终返回true。因为BufferedReader支持mark(), reset()

316 public booleanmarkSupported() {317 return true;318 }319

320 //标记当前BufferedReader的下一个要读取位置。关于readAheadLimit的作用,参考后面的说明。

321 public void mark(int readAheadLimit) throwsIOException {322 if (readAheadLimit < 0) {323 throw new IllegalArgumentException("Read-ahead limit < 0");324 }325 synchronized(lock) {326 ensureOpen();327 //设置readAheadLimit

328 this.readAheadLimit =readAheadLimit;329 //保存下一个要读取的位置

330 markedChar =nextChar;331 //保存“是否忽略换行符”标记

332 markedSkipLF =skipLF;333 }334 }335

336 //重置BufferedReader的下一个要读取位置,337 //将其还原到mark()中所保存的位置。

338 public void reset() throwsIOException {339 synchronized(lock) {340 ensureOpen();341 if (markedChar < 0)342 throw new IOException((markedChar ==INVALIDATED)343 ? "Mark invalid"

344 : "Stream not marked");345 nextChar =markedChar;346 skipLF =markedSkipLF;347 }348 }349

350 public void close() throwsIOException {351 synchronized(lock) {352 if (in == null)353 return;354 in.close();355 in = null;356 cb = null;357 }358 }359 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值