private static int countLines(String str){
String[] lines = str.split("\r\n|\r|\n");
return lines.length;
}
Answer from Tim Schmelter on Stack Overflowprivate static int countLines(String str){
String[] lines = str.split("\r\n|\r|\n");
return lines.length;
}
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
Hello,
I am currently doing some coding homework and it's due at midnight and I'm stuck on this issue. I want to be able to count the number of lines in a text file and stop at a specific character. Here is an example of the text file I'll be reading. Technically it will be a .tgf file but this is what .tfg files look like in Notepad.
0 1 2 3 4 # 2 2 1 3 0 4
I want it to count the number of lines until the "#". We're working on creating our own sort of graph API so 0-4 are the vertices and the count should equal 5. "#" is the separator. The numbers below represent the edges in the graph and I also need to count them so the expected output for the number of edges should be 3. I at first thought that .usedelimiter would be what I needed but it has not been useful. Here is what I've tried:
import java.io.*;
import java.util.*;
public class readGraph{
public static void main (String[] args) throws FileNotFoundException {
File file = new File("../graphtest.txt");
Scanner fileScanner = new Scanner(file);
int count = 0;
while ( fileScanner.hasNextLine()){
count++;
fileScanner.nextLine();
if (fileScanner.nextLine() == "#"){
break;
}
}
System.out.println(count);
}
}java - Count chars, words and lines - Code Review Stack Exchange
Count number of lines in a string in java - BufferedReader behavior - Stack Overflow
count - counting the number of lines in a text file (java) - Stack Overflow
java - Counting number of lines, words, and characters in a text file - Stack Overflow
Bug
The program doesn't count words correctly,
for example in "a text like this",
because it counts every whitespace character as a word,
without handling consecutive whitespace characters.
Reading character by character is inefficient
Reading a file character by character is not very efficient. It would be better to use a buffered reader and process the file line by line. Here's an example of doing that, which also solves the bug with word counting:
long[] counts = new long[3];
try(InputStream in = new FileInputStream(filename);
BufferedReader reader = new BufferedReader(new InputStreamReader(in, Charset.forName("UTF-8")))
) {
String line;
while ((line = reader.readLine()) != null) {
counts[2]++;
counts[1] += line.split("\\s+").length;
counts[0] += line.length() + 1;
}
}
return counts;
This might still not be accurate, and probably there are corner cases where it will not count words correctly, but it's still more accurate than the original.
Encapsulation
The implementation doesn't encapsulate well the results.
It returns a long[],
which is not great because you have to remember the array indexes that correspond to characters, words, lines, which is error prone.
Even if you add constants like CHARS_INDEX = 0, WORDS_INDEX = 1 to eliminate magic numbers,
it will not solve the encapsulation problem:
users of the function will know too much about the internal implementation,
that it uses a long[] for storage.
It would be cleaner to create a dedicated CountResult class to encapsulate the results.
For example:
private static class CountResult {
private final long chars;
private final long words;
private final long lines;
private CountResult(long chars, long words, long lines) {
this.chars = chars;
this.words = words;
this.lines = lines;
}
}
And then use it like this:
long chars = 0;
long words = 0;
long lines = 0;
while ((line = reader.readLine()) != null) {
lines++;
words += line.split("\\s+").length;
chars += line.length() + 1;
}
return new CountResult(chars, words, lines);
Callers will not need to remember indexes, the counts will be accessible intuitively by names.
Unused variables
You have some unused variables:
Reader buffer = new BufferedReader(reader) String newLineChar = System.lineSeparator();
It would be better to remove them.
In every case of the if statement, the line counts[0]++; is executed. You can extract that outside the if statement and drop the last else block.
counts[0]++;
if(character == '\n') {
counts[2]++;
counts[1]++;
} else if(Character.isWhitespace(character)) {
counts[1]++;
}
Having the closing parenthesis of the try clause on it's own line is distracting. At first glance, it seems like it is closing a block and the next line is indented for not reason.
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 are using java 7 or higher version you can directly read all the lines to a List using readAllLines method. That would be easy
readAllLines
List<String> lines = Files.readAllLines(Paths.get(fileName), Charset.defaultCharset());
Then the size of the list will return you number of lines in the file
int noOfLines = lines.size();
If you are using Java 8 you can use streams :
long count = Files.lines(Paths.get(filename)).count();
This will have good performances and is really expressive.
The downside (compared to Thusitha Thilina Dayaratn answer) is that you only have the line count. If you also want to have the lines in a List, you can do (still using Java 8 streams) :
// First, read the lines
List<String> lines = Files.lines(Paths.get(filename)).collect(Collectors.toList());
// Then get the line count
long count = lines.size();
try
int words = 0;
int lines = 0;
int chars = 0;
while(in.hasNextLine()) {
lines++;
String line = in.nextLine();
chars += line.length();
words += new StringTokenizer(line, " ,").countTokens();
}
in.next(); is consuming all the lines in the first while(). After the end of your first while loop, there are no more characters to be read at the input stream.
You should nest your character and word-counting within a while loop counting lines.