62

Need some compact code for counting the number of lines in a string in Java. The string is to be separated by \r or \n. Each instance of those newline characters will be considered as a separate line. For example -

"Hello\nWorld\nThis\nIs\t"

should return 4. The prototype is

private static int countLines(String str) {...}

Can someone provide a compact set of statements? I have a solution at here but it is too long, I think. Thank you.

Naman
  • 27,789
  • 26
  • 218
  • 353
Simon Guo
  • 2,776
  • 4
  • 26
  • 35
  • What happens if the string ends with a newline? Would you count that as another line? So, would "foo\nbar\n" be two lines or three? – Kartick Vaddadi Mar 03 '14 at 09:21
  • 1
    Another way with JDK/11 is to make use of the [`String.lines()`](https://stackoverflow.com/a/50631407/1746118) API. – Naman May 31 '18 at 19:23

16 Answers16

91
private static int countLines(String str){
   String[] lines = str.split("\r\n|\r|\n");
   return  lines.length;
}
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • 38
    While this is perfectly good for almost all use-cases, I just want to point out that this creates a lot of Strings, that are never beeing used - but still requires memory and gc-ing. It probably only a problem on a heavily used server, or a phone or something, but it is still something of a cludge. – KarlP May 17 '10 at 16:09
  • 23
    Its not valid answer. It doesn't work if your String contains only new lines. – kukis Jul 01 '14 at 13:01
  • 2
    @kukis If you want to include trailing newlines you have to pass an explicit argument of -1 for the limit parameter of split (ie str.split("\r\n|\r|\n", -1); if you look at the docs here:http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#split%28java.lang.String,%20int%29 it has more information. – pbuchheit Jun 19 '15 at 16:43
  • Also worth noting. If you use StringUtils from apache commons, their version of 'split' does NOT include trailing newlines. Even if you pass a negative value for length, trailing newlines will still be stripped. – pbuchheit Jun 19 '15 at 16:52
  • 6
    a one liner `int count = text.split("\r\n|\r|\n").length;` – kiedysktos Jun 22 '17 at 07:41
  • 1
    since java 1.1 there is a LineNumberReader. see my answer below. – dermoritz Jan 09 '18 at 07:14
28

How about this:

String yourInput = "...";
Matcher m = Pattern.compile("\r\n|\r|\n").matcher(yourInput);
int lines = 1;
while (m.find())
{
    lines ++;
}

This way you don't need to split the String into a lot of new String objects, which will be cleaned up by the garbage collector later. (This happens when using String.split(String);).

Martijn Courteaux
  • 67,591
  • 47
  • 198
  • 287
26

With Java-11 and above you can do the same using the String.lines() API as follows :

String sample = "Hello\nWorld\nThis\nIs\t";
System.out.println(sample.lines().count()); // returns 4

The API doc states the following as a portion of it for the description:-

Returns:
the stream of lines extracted from this string
Naman
  • 27,789
  • 26
  • 218
  • 353
21

A very simple solution, which does not create String objects, arrays or other (complex) objects, is to use the following:

public static int countLines(String str) {
    if(str == null || str.isEmpty())
    {
        return 0;
    }
    int lines = 1;
    int pos = 0;
    while ((pos = str.indexOf("\n", pos) + 1) != 0) {
        lines++;
    }
    return lines;
}

Note, that if you use other EOL terminators you need to modify this example a little.

Veger
  • 37,240
  • 11
  • 105
  • 116
13

I am using:

public static int countLines(String input) throws IOException {
    LineNumberReader lineNumberReader = new LineNumberReader(new StringReader(input));
    lineNumberReader.skip(Long.MAX_VALUE);
    return lineNumberReader.getLineNumber();
}

LineNumberReader is in the java.io package: https://docs.oracle.com/javase/7/docs/api/java/io/LineNumberReader.html

Freiheit
  • 8,408
  • 6
  • 59
  • 101
dermoritz
  • 12,519
  • 25
  • 97
  • 185
11

If you have the lines from the file already in a string, you could do this:

int len = txt.split(System.getProperty("line.separator")).length;

EDIT:

Just in case you ever need to read the contents from a file (I know you said you didn't, but this is for future reference), I recommend using Apache Commons to read the file contents into a string. It's a great library and has many other useful methods. Here's a simple example:

import org.apache.commons.io.FileUtils;

int getNumLinesInFile(File file) {

    String content = FileUtils.readFileToString(file);
    return content.split(System.getProperty("line.separator")).length;
}
dcp
  • 54,410
  • 22
  • 144
  • 164
  • The line is not from a file, it is just a string. But it is a nice code though – Simon Guo May 17 '10 at 15:24
  • 1
    Shouldn't the FileUtils.readFileToString(file) parameter be a java.io.File instance, your code above is passing a String (I'm using Commons-io 2.4)? – Big Rich May 24 '13 at 12:18
  • @BigRich - Yes, you are right. Thank you for pointing it out, I corrected the code. – dcp May 24 '13 at 13:50
  • This code won't work if you get a file created on Windows and your JVM is on a linux os, and the other way around won't work as well. If you can assume that files are in the format of the os you're running your jvm on, that's ok. – autra Mar 13 '14 at 11:02
  • 1
    @autra - That's more of a general type of problem. You should fix the line endings to be applicable for the given OS before you try to parse the file. Or, if you know the file is in a Windows format (e.g. you know the line ending type), you could code for that as well. I don't really think that's a reason to downvote my answer though, but you're entitled to your opinion. – dcp Mar 13 '14 at 13:08
10

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)

One line solution

Gleb S
  • 403
  • 1
  • 5
  • 13
3

This is a quicker version:

public static int countLines(String str)
{
    if (str == null || str.length() == 0)
        return 0;
    int lines = 1;
    int len = str.length();
    for( int pos = 0; pos < len; pos++) {
        char c = str.charAt(pos);
        if( c == '\r' ) {
            lines++;
            if ( pos+1 < len && str.charAt(pos+1) == '\n' )
                pos++;
        } else if( c == '\n' ) {
            lines++;
        }
    }
    return lines;
}
Saxintosh
  • 322
  • 2
  • 9
1

Try this one:

public int countLineEndings(String str){

    str = str.replace("\r\n", "\n"); // convert windows line endings to linux format 
    str = str.replace("\r", "\n"); // convert (remaining) mac line endings to linux format

    return str.length() - str.replace("\n", "").length(); // count total line endings
}

number of lines = countLineEndings(str) + 1

Greetings :)

Javanaut
  • 48
  • 7
1
//import java.util.regex.Matcher;
//import java.util.regex.Pattern;

private static Pattern newlinePattern = Pattern.compile("\r\n|\r|\n");

public static int lineCount(String input) {
    Matcher m = newlinePattern.matcher(input);
    int count = 0;
    int matcherEnd = -1;
    while (m.find()) {
        matcherEnd = m.end();
        count++;
    }
    if (matcherEnd < input.length()) {
        count++;
    }

    return count;
}

This will count the last line if it doesn't end in cr/lf cr lf

user939857
  • 377
  • 5
  • 19
0
"Hello\nWorld\nthis\nIs\t".split("[\n\r]").length

You could also do

"Hello\nWorld\nthis\nis".split(System.getProperty("line.separator")).length

to use the systems default line separator character(s).

Veger
  • 37,240
  • 11
  • 105
  • 116
aioobe
  • 413,195
  • 112
  • 811
  • 826
  • if it should work correctly with files then it would be `System.getProperty ("line.separator");`. But I thing it's not the case and your previous (before edit) solution was correct. – Roman May 17 '10 at 15:15
0

Well, this is a solution using no "magic" regexes, or other complex sdk features.

Obviously, the regex matcher is probably better to use in real life, as its quicker to write. (And it is probably bug free too...)

On the other hand, You should be able to understand whats going on here...

If you want to handle the case \r\n as a single new-line (msdos-convention) you have to add your own code. Hint, you need another variable that keeps track of the previous character matched...

int lines= 1;

for( int pos = 0; pos < yourInput.length(); pos++){
    char c = yourInput.charAt(pos);
    if( c == "\r" || c== "\n" ) {
        lines++;
    }
}
KarlP
  • 5,149
  • 2
  • 28
  • 41
  • 1
    What if lines are separated by "\r\n" as it is on windows platform? your method will double the line count – Gelin Luo Feb 05 '12 at 22:52
  • As this probably is homework, I just mentioned that case in the answer. You will find it above... – KarlP Feb 06 '12 at 11:13
0
new StringTokenizer(str, "\r\n").countTokens();

Note that this will not count empty lines (\n\n).

CRLF (\r\n) counts as single line break.

volley
  • 6,651
  • 1
  • 27
  • 28
0

This method will allocate an array of chars, it should be used instead of iterating over string.length() as length() uses number of Unicode characters rather than chars.

int countChars(String str, char chr) {
    char[] charArray = str.toCharArray();
    int count = 0;
    for(char cur : charArray)
        if(cur==chr) count++;
    return count;
}
Ghandhikus
  • 839
  • 2
  • 9
  • 12
-1

What about StringUtils.countMatches().

In your case

StringUtils.countMatches("Hello\nWorld\nThis\nIs\t", "\n") + StringUtils.countMatches("Hello\nWorld\nThis\nIs\t", "\r") + 1

should work fine.

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
-2

I suggest you look for something like this

String s; 
s.split("\n\r");

Look for the instructions here for Java's String Split method

If you have any problem, post your code

vodkhang
  • 18,639
  • 11
  • 76
  • 110