readLine方法是BufferedReader中一个非常常用的方法
使用它我们可以从一段输入流中一行一行的读数据
行的区分用"\r","\n"或者是"\r\n",下面就是BufferedReader中readLine的源代码
详细的分析都写在注释里了
String readLine(boolean ignoreLF) throws IOException {
StringBuffer s = null;
int startChar;
synchronized (lock) {
// 确保底层的inputStream未被关闭
ensureOpen();
// ignoreLF在BufferedReader中始终为false
// 而skipLF则会在读到"\r"字符之后被设置为true,通过这样来忽略掉之后的"\n"
boolean omitLF = ignoreLF || skipLF;
// 接下来是两个循环,第一层bufferLoop主要是用来往底层的数组里填充字符,这个底层数组就相当于一个缓冲区
// 而这个缓冲区的大小可以通过BufferedReader(Reader in, int
// sz)这个构造方法的第二个参数来指定,默认为8192bytes
// 而charLoop则是用来遍历底层数组,每次读完底层数组里的数据,就把这些数据写到一个StringBuffer里,
// 直到读到"\r"或"\n"的时候,写入最后一批数据之后就返回结果并退出整个循环
bufferLoop: for (;;) {
// nextChar表示下一个要读的字符的位置、nChars=从inputstream中读入的字符数+nextChar
if (nextChar >= nChars)
fill();
// 读到了inputstream的末尾
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;
// 退出这一层循环有两种情况:1、读到"\r"或者"\n" 2、底层数组cb被读完了
charLoop: for (i = nextChar; i < nChars; i++) {
c = cb[i];
if ((c == '\n') || (c == '\r')) {
eol = true;
break charLoop;
}
}
// 读取底层数组的开始位置
startChar = nextChar;
// 当前读取到的位置
nextChar = i;
// 是否读完了一行(end of line)
if (eol) {
String str;
if (s == null) {
// 这里直接用s不就行了吗。为什么要搞个str变量
str = new String(cb, startChar, i - startChar);
} else {
s.append(cb, startChar, i - startChar);
str = s.toString();
}
// 下一次要读取的位置
nextChar++;
// 下一次若读到"\n"则会忽略掉,而不会终止读
if (c == '\r') {
skipLF = true;
}
return str;
}
// 写入读到的数据
if (s == null)
s = new StringBuffer(defaultExpectedLineLength);
s.append(cb, startChar, i - startChar);
}
}
}