Flask接口签名sign原理与实例代码浅析
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小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~