构造java.util.Scanner的意外行为
我有以下文件 lines.txt
Line1
Line2
Line3
我正在使用扫描仪逐行解析此文件的内容。我在 LinesReader.java 中有以下设置
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
class Line {
Line(String content) {
this.content = content;
}
public String content;
public String toString() {
return content;
}
}
public class LinesReader {
public static Line buildLine(InputStream is) {
Scanner scanner = new Scanner(is);
if (scanner.hasNextLine()) {
return new Line(scanner.nextLine());
}
return null;
}
public static Line buildLine(Scanner scanner) {
if (scanner.hasNextLine()) {
return new Line(scanner.nextLine());
}
return null;
}
public static void main(String[] args) throws FileNotFoundException {
List<Line> lines = new ArrayList<>();
Line line = null;
FileInputStream is = new FileInputStream("lines.txt");
// buildLine(scanner) works as expected
while ((line = buildLine(is)) != null) {
lines.add(line);
}
System.err.println(lines);
}
}
输出是
[Line1]
预期的输出将是
[Line1, Line2, Line3]
我了解 Scanner 实现了 AutoCloseable,但根据仅适用于try-with-resources构造而不适用于
此处的文档。另外,当我调试时,它说底层流是打开的。第二次调用scanner.hasNextLine()意外失败。
如果我在 main() 中构造一次扫描器,它会按预期工作。
我的java版本是1.8.0_275
为了回应@Sweeper 的评论,扫描仪似乎缓冲的比消耗的多,文档有点矛盾。
为了 hasNextLine()
扫描仪不会通过任何输入。
为了 nextLine()
由于此方法继续搜索输入以寻找行分隔符,因此如果不存在行分隔符,它可能会缓冲所有搜索要跳过的行的输入。
强调我的。
回答
的文档 hasNextLine()
扫描仪不会通过任何输入。
有点误导。它不会提前扫描器的内部缓冲区,这是显而易见的,但会读取数千字节的流。
在这种情况下,整个流被消耗 hasNextLine()。
我个人的看法是,这是Scanner实现的一个缺陷。扫描仪的设计是为了方便和简单,而不是为了性能。将 InputStream 包装在 BufferedInputStream 中是明智的,并使使用更简单。