计算 java 中字符串中的行数 - BufferedReader 行为

Count number of lines in a string in java - BufferedReader behavior

我正在使用函数 countLines 来计算字符串中的行数。它使用 StringReader 和 BufferedReader。但是我得到的结果与我在示例中对字符串 test 的预期结果不同。有人可以验证这种情况并判断 BufferedReader 的行为是否符合预期。

package test;

import java.io.BufferedReader;
import java.io.StringReader;

public class LineCountTest {

    private static final String test = "This is a\ntest string\n\n\n";
    private static final String test2 = "This is a\ntest string\n\n\n ";

    public static void main(String[] args) {
        System.out.println("Line count: " + countLines(test));
        System.out.println("Line count: " + countLines(test2));
    }

    private static int countLines(String s) {
        try (
                StringReader sr = new StringReader(s);
                BufferedReader br = new BufferedReader(sr)
        ) {
            int count = 0;
            for (String line = br.readLine(); line != null; line = br.readLine()) {
                count++;
            }
            return count;
        } catch (Exception e) {
            return -1;
        }
    }

}

我希望 countLines 在这两种情况下都达到 return 5,但是 returns 4第一个字符串。

背景:我实际上需要 line 的值来填充字符串数组,并希望最后一个元素是空字符串。

编辑:我已经知道

String[] lines = s.split("\n", -1);
int count = lines.length;

会给我 correct/expected 行数。我只询问性能原因,以及是否有人可以判断 BufferedReader 的行为是否正确。

所以你发现最后一行以 \n 结尾或非空时被识别。

出于您的目的,您可以使用:

String[] lines = "This is a\ntest string\n\n\n".split("\r?\n", 5);

这确保数组将有 5 个元素。正则表达式拆分虽然有点慢。

检查此 code

class LineCountTest
{
    private static final String test = "This is a\ntest string\n\n\n";
    private static final String test2 = "This is a\ntest string\n\n\n ";

    public static void main(String[] args) {
        System.out.println("Line count: " + countLines(test));
        System.out.println("Line count: " + countLines(test2));
    }

    private static int countLines(String s) {
        return (s + " ").split("\r?\n").length;
    }
}

这将解决您的问题。

此代码按 \r\n\n 和 return 行数拆分字符串。

添加了额外的空格space,这样即使最后一行为空,也会计算在内。

BufferedReader 运行正常。

条件 line != null 导致了问题。

在字符串test中,最后一个\n后有nothing,被[=18=读为null ] 这就是循环终止且输出为 4.

的原因

在字符串test2中,在最后一个\n之后有一个空白space,这样就可以再次迭代,输出为5.

如果您在第一个字符串中添加额外的 space。

private static final String test = "This is a\ntest string\n\n\n ";

你会得到相同的计数。 主要原因是在for循环中:

for (String line = br.readLine(); line != null; line = br.readLine()) 
{
        count++;
}

for 循环的第三个参数"line = br.readLine()"只有return一个字符串,如果在“\n”之后有可用的任何其他字符串。在你的第一个字符串中没有其他字符,但在你的第二个字符串中你添加了一个 space 并且这个 space 现在被视为一个新字符串。这就是为什么你得到 4 和 5 计数的原因。

如果您使用 Java 8 那么:

long lines = stringWithNewlines.chars().filter(x -> x == '\n').count() + 1;

(最后+1是如果字符串被裁剪算到最后一行)​​