No te muestra la primera porque haces una lectura antes de entrar en el while que no se está mostrando en pantalla.
Usar FileReader puede ser tedioso en este caso, porque va carácter a carácter.
Se podría usar junto con BufferedReader, esta clase se construye a partir de un FileReader y te permite leer líneas enteras devueltas en la clase String.
Por cada línea String obtenida, se podría contar las palabras usando una expresión regular o bien dividiendo el String usando su método split().
Si a este método le pasamos como argumento un espacio en blanco -> split(" "), dividirá cada String en "trozos" haciendo "cortes" allá donde encuentre un espacio en blanco, y dichos trozos los retorna en un array de String[].
Estos trozos, serían las palabras, así que bastaría con preguntar cuándo mide el array retornado, sumarlo en una variable acumuladora y repetir el mismo proceso con la siguiente línea.
Sin embargo, puesto que básicamente solo queremos contar palabras, todo esto se puede simplificar mucho más si usamos la clase Scanner.
Esta clase solemos usarla para recibir datos por teclado por parte del usuario. Sin embargo también sirve para "recibir datos" por otras vías, por ejemplo, de un archivo de texto plano. (mediante un objeto File)
Además cuenta con dos métodos muy útiles para este ejercicio.
Con el método next() nos devuelve directamente una palabra, es decir, lee caracteres hasta encontrar un espacio en blanco. Así que nos va a proporcionar palabras, que podremos mostrar y contar.
Y con el método hasNext(), nos dice si aún queda alguna palabra o no por recibir, así podremos usarlo como condición de bucle para que repetir el proceso de leer palabras y contarlas, mientas que hasNext() devuelva valor
trueAsí que el código para hacerlo, puede ser tan sencillo como este:
public class ContarPalabras {
public static void main(String[] args) {
Scanner lector;
int contador = 0;
try {
lector = new Scanner(new File("D:/poema.txt"));
while(lector.hasNext()) {
System.out.println("Palabra: " + lector.next()); //Mostramos palabra leída
contador++; //La contamos
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
System.out.println("\nTotal palabras contadas: " + contador);
}
}
El uso de try catch es obligatorio.
Bien, mi archivo poema.txt que uso en el código tiene este texto:
Caminante, son tus huellas
el camino y nada más;
Caminante, no hay camino,
se hace camino al andar.
Al andar se hace el camino,
y al volver la vista atrás
se ve la senda que nunca
se ha de volver a pisar.
Caminante no hay camino
sino estelas en la mar.
Y si ejecuto el programa, obtengo este resultado en pantalla:
Palabra: Caminante,
Palabra: son
Palabra: tus
Palabra: huellas
Palabra: el
Palabra: camino
Palabra: y
Palabra: nada
Palabra: más;
Palabra: Caminante,
Palabra: no
Palabra: hay
Palabra: camino,
Palabra: se
Palabra: hace
Palabra: camino
Palabra: al
Palabra: andar.
Palabra: Al
Palabra: andar
Palabra: se
Palabra: hace
Palabra: el
Palabra: camino,
Palabra: y
Palabra: al
Palabra: volver
Palabra: la
Palabra: vista
Palabra: atrás
Palabra: se
Palabra: ve
Palabra: la
Palabra: senda
Palabra: que
Palabra: nunca
Palabra: se
Palabra: ha
Palabra: de
Palabra: volver
Palabra: a
Palabra: pisar.
Palabra: Caminante
Palabra: no
Palabra: hay
Palabra: camino
Palabra: sino
Palabra: estelas
Palabra: en
Palabra: la
Palabra: mar.
Total palabras contadas: 51
Es un código sencillo y efectivo.
No contempla posibles casos muy concretos, como que un texto tenga símbolos separados de las palabras.
Si en mi texto de ejemplo separo los puntos y comas de las palabras que les preceden (lo cuál no es ortográficamente correcto), entonces Scanner también los considerará como palabras y dará un resultado erróneo.
Palabra: Caminante
Palabra: ,
Palabra: son
Palabra: tus
Palabra: huellas
Palabra: el
Palabra: camino
Palabra: y
Palabra: nada
Palabra: más
Palabra: ;
Palabra: Caminante
Palabra: ,
Palabra: no
Palabra: hay
Palabra: camino
Palabra: ,
Palabra: se
Palabra: hace
Palabra: camino
Palabra: al
Palabra: andar
Palabra: .
Palabra: Al
Palabra: andar
Palabra: se
Palabra: hace
Palabra: el
Palabra: camino
Palabra: ,
Palabra: y
Palabra: al
Palabra: volver
Palabra: la
Palabra: vista
Palabra: atrás
Palabra: se
Palabra: ve
Palabra: la
Palabra: senda
Palabra: que
Palabra: nunca
Palabra: se
Palabra: ha
Palabra: de
Palabra: volver
Palabra: a
Palabra: pisar
Palabra: .
Palabra: Caminante
Palabra: no
Palabra: hay
Palabra: camino
Palabra: sino
Palabra: estelas
Palabra: en
Palabra: la
Palabra: mar
Palabra: .
Total palabras contadas: 59
Así que se podría aumentar código para descartar todos los posibles símbolos como palabras...
Pero bueno, es algo opcional, se supone que nuestro programa va a recibir un texto correcto, y no una chapuza xD.
Si algo no te ha quedado claro, no dudes en preguntar.
Si por algún motivo no puedes usar la clase Scanner, porque se supone que has de usar obligatoriamente BufferedReader y/o FileReader, dilo y buscamos otra solución
Lo de usar split() funcionaría con BufferedReader.
Si tuvieramos que limitarnos a usar solo FileReader, pues casi mejor pegarnos un tiro
, pero bueno, supongo que también se podría desarrollar una solución.
Un saludo.