readLine
- BufferedReader 类继承自 Reader,又新增了按行读取的方法:
String readLine()
,该方法返回改行不包含结束符的字符串内容,如果已到达流末尾,则返回null
; - 使用范例如下:
public class Test {
public static void main(String[] args) throws IOException {
// 创建流对象
BufferedReader br = new BufferedReader(new FileReader("C:\\Users\\80626\\Desktop\\1.txt"));
// 定义字符串,保存读取的一行文字
String line = null;
// 循环读取,读取到最后返回null
while ((line = br.readLine()) != null) {
System.out.print(line);
System.out.println("------");
}
// 释放资源
br.close();
}
}
1. API 中的方法
public String readLine() throws IOException {
return readLine(false);
}
- 其实调用了
String readLine(boolean ignoreLF)
方法,ignoreLF = true
时忽略下一个换行符'\n'
;
/** If the next character is a line feed, skip it */
private boolean skipLF = false;
- BufferedReader 类的私有变量
skipLF = false
; - 阅读说明可知,
readLine()
方法的主要功能是读取一行文本,换行符'\n'
,回车符'\r'
,换行符后的回车符,或到达文件结尾都被认为是终止的。它会返回一个包含该行内容的字符串,不包括任何行终止字符,如果到达流的末尾而没有读取任何字符,则为null
。readLine()
的方法如下:
String readLine(boolean ignoreLF) throws IOException {
StringBuffer s = null;
int startChar;
synchronized (lock) {
ensureOpen();
boolean omitLF = ignoreLF || skipLF;
bufferLoop:
for (;;) {
if (nextChar >= nChars)
fill();
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;
charLoop:
for (i = nextChar; i < nChars; i++) {
c = cb[i];
if ((c == '\n') || (c == '\r')) {
eol = true;
break charLoop;
}
}
startChar = nextChar;
nextChar = i;
if (eol) {
String str;
if (s == null) {
str = new String(cb, startChar, i - startChar);
} else {
s.append(cb, startChar, i - startChar);
str = s.toString();
}
nextChar++;
if (c == '\r') {
skipLF = true;
}
return str;
}
if (s == null)
s = new StringBuffer(defaultExpectedLineLength);
s.append(cb, startChar, i - startChar);
}
}
}
- 阅读 BufferedReader 类,有一个私有的类变量
defaultCharBufferSize
:
private static int defaultCharBufferSize = 8192;
- 可见,
readLine()
调用了一个死循环,会不断往 Buffer 里添加数据,如果不指定 Buffer 大小,则readLine()
使用的 Buffer 有 8192 个字符(8*1024),在达到 Buffer 大小之前,只有遇到/r
、/n
、/r/n
才会返回; - 使用 socket 之类的数据流时,要避免使用
readLine()
,以免为了等待一个换行或回车符而一直阻塞;
2. 网络模式注意事项
- 在网络上,
readLine()
是阻塞模式,也就是说如果readLine()
读取不到数据的话,会一直阻塞,而不是返回null
,所以如果你想要在 while 循环后执形相关操作是不可能的,因为里面是一个死循环,一旦读不到数据,它又开始阻塞,因此永远也无法执形 while 循环外面的操作,所以应该把操作放在 while 循环里面; - 在 while 循环里面判断
readLine()!= null
的时候要赋值给一个 String,因为如果不为null
,那么这时候已经读了一行。如果用while (br.readLine()!=null)
,那么下面没法再获取到这一行,所以应该用while ((line = br.readLine())!=null){}
; readLine()
通过下列字符之一即可认为某行已终止:换行'\n'
、回车'\r'
或回车后直接跟着换行,所以我们在发送数据的时候要再后面加上这些标志符,否则程序会阻塞。而直接用下面这种方法:PrintStream ps = new PrintStream(socket.getOutputStream(), true, "UTF-8");ps.println();
,ps.println()
已经包含换行了,所以不要用print()
,若是要就要在后面加上换行符;readLine()
只有在数据流发生异常或者另一端被close()
掉时,才会返回null
值。
推荐阅读:Java buffered stream 缓冲流 >>>