Ich kam zu dem Schluss, dass wc -l
: s Methode zum Zählen von Zeilenumbrüchen in Ordnung ist, aber nicht intuitive Ergebnisse für Dateien zurückgibt, bei denen die letzte Zeile nicht mit einem Zeilenumbruch endet.
Die auf LineNumberReader basierende @ er.vikas-Lösung, bei der jedoch eine zur Zeilenanzahl hinzugefügt wurde, ergab nicht intuitive Ergebnisse für Dateien, bei denen die letzte Zeile mit einer neuen Zeile endet.
Ich habe daher ein Algo erstellt, das wie folgt funktioniert:
@Test
public void empty() throws IOException {
assertEquals(0, count(""));
}
@Test
public void singleNewline() throws IOException {
assertEquals(1, count("\n"));
}
@Test
public void dataWithoutNewline() throws IOException {
assertEquals(1, count("one"));
}
@Test
public void oneCompleteLine() throws IOException {
assertEquals(1, count("one\n"));
}
@Test
public void twoCompleteLines() throws IOException {
assertEquals(2, count("one\ntwo\n"));
}
@Test
public void twoLinesWithoutNewlineAtEnd() throws IOException {
assertEquals(2, count("one\ntwo"));
}
@Test
public void aFewLines() throws IOException {
assertEquals(5, count("one\ntwo\nthree\nfour\nfive\n"));
}
Und es sieht so aus:
static long countLines(InputStream is) throws IOException {
try(LineNumberReader lnr = new LineNumberReader(new InputStreamReader(is))) {
char[] buf = new char[8192];
int n, previousN = -1;
//Read will return at least one byte, no need to buffer more
while((n = lnr.read(buf)) != -1) {
previousN = n;
}
int ln = lnr.getLineNumber();
if (previousN == -1) {
//No data read at all, i.e file was empty
return 0;
} else {
char lastChar = buf[previousN - 1];
if (lastChar == '\n' || lastChar == '\r') {
//Ending with newline, deduct one
return ln;
}
}
//normal case, return line number + 1
return ln + 1;
}
}
Wenn Sie intuitive Ergebnisse wünschen, können Sie diese verwenden. Wenn Sie nur wc -l
Kompatibilität wünschen , verwenden Sie einfach die @ er.vikas-Lösung, fügen Sie jedoch keine zum Ergebnis hinzu und wiederholen Sie den Sprung:
try(LineNumberReader lnr = new LineNumberReader(new FileReader(new File("File1")))) {
while(lnr.skip(Long.MAX_VALUE) > 0){};
return lnr.getLineNumber();
}