J'ai conclu que wc -l
: s la méthode de comptage des sauts de ligne est correcte mais renvoie des résultats non intuitifs sur les fichiers où la dernière ligne ne se termine pas par une nouvelle ligne.
Et la solution @ er.vikas basée sur LineNumberReader mais en ajoutant un au nombre de lignes a renvoyé des résultats non intuitifs sur les fichiers où la dernière ligne se termine par un retour à la ligne.
J'ai donc fait un algo qui gère comme suit:
@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"));
}
Et cela ressemble à ceci:
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;
}
}
Si vous voulez des résultats intuitifs, vous pouvez l'utiliser. Si vous voulez juste de la wc -l
compatibilité, utilisez simplement la solution @ er.vikas, mais n'en ajoutez pas une au résultat et réessayez de sauter:
try(LineNumberReader lnr = new LineNumberReader(new FileReader(new File("File1")))) {
while(lnr.skip(Long.MAX_VALUE) > 0){};
return lnr.getLineNumber();
}