简体   繁体   中英

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

I am using the function countLines to count the number of lines in a string. It uses StringReader and BufferedReader. But I get a different result than I expected for the string test in my example. Can somebody verify this scenario and tell if BufferedReader behaves as expected.

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;
        }
    }

}

I expected countLines to return 5 in both cases, but it returns 4 for the first string.

Background: I actually need the value of line to fill an array of strings and expected the last element to be the empty string.

Edit: I already know that

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

will give me the correct/expected number of lines. I only ask for performance reasons and if somebody can tell if BufferedReader behaves correctly.

Check this 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;
    }
}

This will solve your problem.

This code splits the string by \\r\\n or \\n and return the number of lines.

The additional blank space is added so that the last line is counted even if it is empty.

The BufferedReader is behaving correctly.

The condition line != null is causing the problem.

In the string test , there is nothing after the last \\n , which is read as null by BufferedReader#readLine() and thats why the loop terminates and the output is 4 .

In the string test2 , there is a blank space after the last \\n , which allows another iteration and the output is 5 .

So you found that a last line is recognized when it ends with a \\n or is non-empty.

For your purposes one might be able to use:

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

This assures that the array will have 5 elements. Regex split is a bit slower though.

if you add an extra space in your first string.

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

you will get both same count. The main reason is in for loop :

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

third parameter of for loop "line = br.readLine()" only return a string if after "\\n" is there available any other string . in your first string there have no other character but in your second string you add a space and this space now consider as a new string. that's why you get 4 and 5 count number.

If you use Java 8 then:

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

(+1 in the end is to count last line if string is trimmed)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM