Java|Java BufferedReader相关源码实例分析
1、案例代码
假设b.txt存储了abcdegfhijk
public static void main(String[] args) throws IOException {//字符缓冲流BufferedReader bufferedReader=new BufferedReader(new FileReader(new File("H:\\ioText\\b.txt")),8); //存储读取的数据char[] charsRead=new char[5]; //读取数据bufferedReader.read(charsRead); //遍历并输出charsReadfor (char c:charsRead){System.out.println(c); }}
2、通过源码(部分)分析案例
a、第一次读取
public class BufferedReader extends Reader {private Reader in; //字符流private char cb[]; //缓冲区private int nChars, nextChar; //nChars缓冲区可读字符数,nextChar下一个字符位置private static final int INVALIDATED = -2; private static final int UNMARKED = -1; private int markedChar = UNMARKED; private int readAheadLimit = 0; private boolean skipLF = false; private boolean markedSkipLF = false; private static int defaultCharBufferSize = 8192; //缓冲区默认大小private static int defaultExpectedLineLength = 80; //案例调用的构造方法public BufferedReader(Reader in, int sz) {//调用父类构造super(in); //判断缓冲区大小是否正常if (sz <= 0)throw new IllegalArgumentException("Buffer size <= 0"); //用户传入的字符流this.in = in; //给缓冲区指定空间大小(案例指定为8)cb = new char[sz]; //缓冲区可读字符数和下一个字符位置初始化为0nextChar = nChars = 0; }//读取数据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; }//调用read1方法进行读取(真正读取数据的方法是read1方法)int n = read1(cbuf, off, len); if (n <= 0) return n; //将之前没处理完的数据复制到自定以数组charsRead再次调用read1方法读取while ((n < len) && in.ready()) {int n1 = read1(cbuf, off + n, len - n); if (n1 <= 0) break; n += n1; }return n; }}//cbuf用户自定义数组(charsRead),off=0,len=5private int read1(char[] cbuf, int off, int len) throws IOException {if (nextChar >= nChars) {//第一次读nextChar、nChars都为0,满足条件if (len >= cb.length && markedChar <= UNMARKED && !skipLF) {return in.read(cbuf, off, len); }//刷新缓冲区,先往下找到fill方法源码分析fill(); }if (nextChar >= nChars) return -1; if (skipLF) {skipLF = false; if (cb[nextChar] == '\n') {nextChar++; if (nextChar >= nChars)fill(); if (nextChar >= nChars)return -1; }}//执行完fill方法到这里,(len=5,nChars - nextChar=8-0)->n=5int n = Math.min(len, nChars - nextChar); //将缓冲区cb从nextChar开始复制n=5个字符到自定义数组System.arraycopy(cb, nextChar, cbuf, off, n); //nextChar=5nextChar += n; //n=5return n; }//刷新缓冲区方法private void fill() throws IOException {int dst; if (markedChar <= UNMARKED) {//markedChar初始值为UNMARKED,满足条件/* No mark */dst = 0; //初始化dst} 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 {//dst=0,cb.length - dst=8-0->n=8n = in.read(cb, dst, cb.length - dst); } while (n == 0); if (n > 0) {//满足条件//nChars=8nChars = dst + n; //nextChar=0nextChar = dst; }}}
第一次读取后charsRead存储了五个字符:abcde
b、第二次读取
//cbuf用户自定义数组(charsRead),off=0,len=5private int read1(char[] cbuf, int off, int len) throws IOException {if (nextChar >= nChars) {//第二次读nextChar=5、nChars=8,不满足条件if (len >= cb.length && markedChar <= UNMARKED && !skipLF) {return in.read(cbuf, off, len); }fill(); }if (nextChar >= nChars) return -1; if (skipLF) {skipLF = false; if (cb[nextChar] == '\n') {nextChar++; if (nextChar >= nChars)fill(); if (nextChar >= nChars)return -1; }}//跳过if直接到这里,len=5,nChars - nextChar=8-5=3->n=3int n = Math.min(len, nChars - nextChar); //将缓冲区cb从nextChar=5开始复制n=3个字符到自定义数组System.arraycopy(cb, nextChar, cbuf, off, n); //nextChar=5+3=8nextChar += n; //n=8return n; }
第二次读取只读了三个字符把charsRead五个字符的前三个覆盖:fghde
c、第三次读取
//cbuf用户自定义数组(charsRead),off=0,len=5private int read1(char[] cbuf, int off, int len) throws IOException {if (nextChar >= nChars) {//第三次读nextChar=8、nChars=8,满足条件if (len >= cb.length && markedChar <= UNMARKED && !skipLF) {return in.read(cbuf, off, len); }//刷新缓冲区,先往下找到fill方法源码分析fill(); }if (nextChar >= nChars) return -1; if (skipLF) {skipLF = false; if (cb[nextChar] == '\n') {nextChar++; if (nextChar >= nChars)fill(); if (nextChar >= nChars)return -1; }}//执行完fill方法到这里,(len=2,nChars - nextChar=8-0)->n=2int n = Math.min(len, nChars - nextChar); //将缓冲区cb从nextChar=0开始复制n=2个字符到自定义数组System.arraycopy(cb, nextChar, cbuf, off, n); //nextChar=5+3=8nextChar += n; //n=8return n; }//刷新缓冲区方法private void fill() throws IOException {int dst; if (markedChar <= UNMARKED) {//markedChar初始值为UNMARKED,满足条件/* No mark */dst = 0; //初始化dst} 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 {//dst=0,cb.length - dst=8-0->n=8n = in.read(cb, dst, cb.length - dst); } while (n == 0); if (n > 0) {//满足条件//nChars=8nChars = dst + n; //nextChar=0nextChar = dst; }}}
第三次读取了两个字符到charsRead,把最后两个字符覆盖:fghijk
3、源码执行过程图解
文章图片
【Java|Java BufferedReader相关源码实例分析】以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 事件代理
- Java|Java OpenCV图像处理之SIFT角点检测详解
- java中如何实现重建二叉树
- 数组常用方法一
- 【Hadoop踩雷】Mac下安装Hadoop3以及Java版本问题
- Java|Java基础——数组
- RxJava|RxJava 在Android项目中的使用(一)
- java之static、static|java之static、static final、final的区别与应用
- Java基础-高级特性-枚举实现状态机