Java BufferedReader相关源码实例分析

网友投稿 264 2022-11-15


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);

//遍历并输出charsRead

for (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];

//缓冲区可读字符数和下一个字符位置初始化为0

nextChar = 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=5

private 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=5

int n = Math.min(len, nChars - nextChar);

//将缓冲区cb从nextChar开始复制n=5个字符到自定义数组

System.arraycopy(cb, nextChar, cbuf, off, n);

//nextChar=5

nextChar += n;

//n=5

return n;

}

//刷新缓冲区方法

private void fill() throws IOException {

int dst;

if (mahttp://rkedChar <= 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=8

n = in.read(cb, dst, cb.length - dst);

} while (n == 0);

if (n > 0) {//满足条件

//nChars=8

nChars = dst + n;

//nextChar=0

nextChar = dst;

}

}

}

第一次读取后charsRead存储了五个字符:abcde

b、第二次读取

//cbuf用户自定义数组(charsRead),off=0,len=5

private int read1(char[] cbuf, int off, int len) throws IOException {

if (nextChar >= nChars) {//第二次读nextChar=5、nChars=8,不满足条件

if (len >= cb.length && markedChar <= UNMARKED && !skipLF) {

XwWqSMq 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=3

int n = Math.min(len, nChars - nextChar);

//将缓冲区cb从nextChar=5开始复制n=3个字符到自定义数组

System.arraycopy(cb, nextChar, cbuf, off, n);

//nextChar=5+3=8

nextChar += n;

//n=8

return n;

}

第二次读取只读了三个字符把charsRead五个字符的前三个覆盖:fghde

c、第三次读取

//cbuf用户自定义数组(charsRead),off=0,len=5

private 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=2

int n = Math.min(len, nChars - nextChar);

//将缓冲区cb从nextChar=0开始复制n=2个字符到自定义数组

System.arraycopy(cb, nextChar, cbuf, off, n);

//nextChar=5+3=8

nextChar += n;

//n=8

return 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=8

n = in.read(cb, dst, cb.length - dst);

} while (n == 0);

if (n > 0) {//满足条件

//nChars=8

nChars = dst + n;

//nextChar=0

nextChar = dst;

}

}

}

第三次读取了两个字符到charsRead,把最后两个字符覆盖:fghijk

3、源码执行过程图解


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java实现线性表的链式存储
下一篇:Springboot 1.5.7整合Kafka
相关文章

 发表评论

暂时没有评论,来抢沙发吧~