为什么在 BufferedReader 期间检查每行 isEmpty 对 Java 逐行读取文件会有所不同

Why checking isEmpty each row during BufferedReader makes a difference in Java reading file line by line

提问人:toy 提问时间:10/11/2023 最后编辑:toy 更新时间:10/11/2023 访问量:66

问:

我有一段代码正在读取一个文件。文件的内容只是每行的一个 ID。没什么特别的。但是,我不确定为什么此代码的每种样式都会产生不同的结果。

文件的内容如下所示

a9c536f6-592f-4458-b61b-6ed3f875e990
d6b384d3-8fae-2dd3-ed06-b57cb65b093c
31474dd6-5c3b-4dc4-82cb-7e05121a77e1
b37dd457-da49-4972-9e3d-cd642e975562
f88df909-35bc-453c-b706-d48b5a11af9a
5d75083b-c4a8-4ad1-8494-645aaabfb283
85d8170e-8982-43c2-b574-9d7fe96d1b46
68bf33d0-1b5e-480c-83f2-ae38d9e0c8c8
26ea9d4a-f509-43b2-850f-cc445dccfd33
f9e9bd88-f67d-4e66-b281-eceeb57985eb
    @Test
    void testReadFile() throws Exception
    {
        String fileName = "/Users/user/Downloads/payload";
        // #1
        BufferedReader reader = new BufferedReader(new FileReader(fileName));
        Set<String> readUsingCollect = reader.lines().filter(l -> !l.isEmpty()).collect(Collectors.toSet());

        reader = new BufferedReader(new FileReader(fileName));
        String row;

        // #2
        Set<String> readUsingNonEmpty = new HashSet<>();
        while ((row = reader.readLine()) != null && !row.isEmpty()) {
            readUsingNonEmpty.add(row);
        }

        reader = new BufferedReader(new FileReader(fileName));

        // #3
        String row1;
        Set<String> readNonCheckingNonEmpty = new HashSet<>();
        int counter = 0;
        while ((row1 = reader.readLine()) != null) {
            if (row1.isEmpty()) {
                counter += 1;
            }
            readNonCheckingNonEmpty.add(row1);
        }

        Sets.SetView<String> difference = Sets.difference(readNonCheckingNonEmpty, readUsingNonEmpty);

        System.out.println("Size readUsingCollect: " + readUsingCollect.size());
        System.out.println("Size readUsingNonEmpty: " + readUsingNonEmpty.size());
        System.out.println("Size readNonCheckingNonEmpty: " + readNonCheckingNonEmpty.size());
        System.out.println("Counter: " + counter);
        System.out.println("Difference in size: " + difference.size());
        reader.close();
    }

下面是运行上述代码的结果

Size readUsingCollect: 7525
Size readUsingNonEmpty: 5498
Size readNonCheckingNonEmpty: 7526
Counter: 2
Difference in size: 2028

我想知道为什么 #2 产生的结果与 #3 和 #1 不同。文件的内容没有空行。最让我困惑的是,我希望 #1 和 #2 是相同的,但它们是不同的。

Java BufferedReader 文件读取器

评论

0赞 Sweeper 10/11/2023
我高度怀疑中间某处一条空线,因为 和 相差 1。每当读取一行时,都会递增一个计数器,当您到达空行时,打印该计数器。readUsingCollectreadNonCheckingNonEmpty
1赞 berse2212 10/11/2023
尝试打印出您读取的数据并进行比较。也许这显示了差异。
0赞 toy 10/11/2023
我更新了代码以具有计数器,但计数器仅显示 2。但是检查内联 isEmpty 和 not 之间的区别与集合的大小有很大不同。
2赞 Cwift 10/11/2023
while ((row = reader.readLine()) != null && !row.isEmpty())如果该行不为 null 且为空,则中断
0赞 Thomas Kläger 10/11/2023
@Cwift这是正确的答案。方法 #2 在第一个空行处停止读取数据。请将您的评论转换为答案,以便我投赞成票。(也许可以展示如何在使用方法 #2 时正确过滤掉空行)

答:

1赞 Thomas Kläger 10/11/2023 #1

正如@Cwift评论中提到的:

方法 #2 的问题在于

    while ((row = reader.readLine()) != null && !row.isEmpty()) {}

不过滤空行 - 它会在第一个空行处终止循环

如果要读取整个文件并过滤掉空行,则需要将方法#2实现为:

    Set<String> readUsingNonEmpty = new HashSet<>();
    while (row = reader.readLine()) {
        if (!row.isEmpty()) {
            readUsingNonEmpty.add(row);
        }
    }

评论

0赞 Cwift 10/11/2023
谢谢你为我发布它。我仍然想知道为什么 #1 与 #3 不同。
1赞 Thomas Kläger 10/11/2023
@Cwift井 #1 过滤掉空行 (),#3 计算空行,但无论如何都将它们添加到结果集中。由于空字符串被认为是相等的,因此结果集中最多只能有一个空字符串,这就是为什么 #3 在结果集中还有一个条目的原因。.filter(l -> !l.isEmpty())