构造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 中是明智的,并使使用更简单。


以上是构造java.util.Scanner的意外行为的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>