java - ¿Por qué hasNext() False, pero hasNextLine() es True?
java.util.scanner (5)
Pregunta
¿Cómo es que para un objeto de escáner el método
hasNextLine()
devuelve verdadero mientras que el método
hasNext()
devuelve falso?
Nota: Según el archivo de entrada, el método
hasNext()
devuelve el resultado como se esperaba;
hasNextLine()
no devuelve el resultado correcto.
Código
Aquí está el código que estoy ejecutando que está creando los resultados a continuación:
public void ScannerTest(Reader fileReaderObject){
Scanner scannerObj = new Scanner(fileReaderObject);
for(int i = 1; scannerObj.hasNext(); i++){
System.out.println(i + ": " + scannerObj.next());
System.out.println("Has next line: " + scannerObj.hasNextLine());
System.out.println("Has next: " + scannerObj.hasNext());
}
System.out.println();
scannerObj.close();
}
Fichero de entrada
El siguiente es el contenido real del archivo que estoy pasando a este escáner:
a 3 9
b 3 6
c 3 3
d 2 8
e 2 5
f 2 2
g 1 7
h 1 4
i 1 1
Resultado
El siguiente es el final de lo que se imprime en la consola cuando ejecuto mi código, e incluye la parte que no puedo entender:
25: i
Has next line: true
Has next: true
26: 1
Has next line: true
Has next: true
27: 1
Has next line: true
Has next: false
Respuesta corta
Tiene una línea vacía al final del archivo.
Motivo de la línea vacía.
Si toma su contenido y lo guarda, por ejemplo, en un archivo txt, algunos editores agregarán una nueva línea vacía a su archivo.
Los editores se comportan de esta manera, porque esto es parte del estándar POSIX :
Línea 3.206
Una secuencia de cero o más no caracteres más un carácter de terminación.
Este tema ha sido discutido en este hilo .
Documentación de Java Scanner
Aquí está la documentación de la clase Java 8 Scanner .
hasNext()
Devuelve verdadero si este escáner tiene otro token en su entrada.
hasNextLine()
Devuelve verdadero si hay otra línea en la entrada de este escáner.
Motivo del comportamiento del código Java
Debido a los hechos descritos anteriormente,
hasNextLine()
devolverá
true
, pero
hasNext()
no puede encontrar nada, lo que puede reconocer como
Token
y, por lo tanto, devuelve
false
.
Para obtener información adicional, consulte la publicación durron597 .
Tiene una nueva línea adicional al final de su archivo.
-
hasNextLine()
comprueba si hay otrolinePattern
en el búfer. -
hasNext()
comprueba si hay un token analizable en el búfer, separado por el delimitador del escáner.
Dado que el delimitador del escáner es un espacio en blanco y el
linePattern
también es un espacio en blanco, es posible que haya un
linePattern
en el búfer pero no tokens analizables.
Por lo general, la forma más común de lidiar con este problema siempre llama a
nextLine()
después de analizar todos los tokens (por ejemplo, números) en cada línea de su texto.
Debe hacer esto cuando use
Scanner
cuando lea la entrada de un usuario también de
System.in
.
Para avanzar el escáner más allá de este delimitador de espacios en blanco, debe usar
scanner.nextLine()
para borrar el delimitador de línea.
Consulte:
Uso de scanner.nextLine ()
Apéndice:
LinePattern
se define como un
Pattern
que coincide con esto:
private static final String LINE_SEPARATOR_PATTERN =
"/r/n|[/n/r/u2028/u2029/u0085]";
private static final String LINE_PATTERN = ".*("+LINE_SEPARATOR_PATTERN+")|.+$";
El delimitador de token predeterminado es este
Pattern
:
private static Pattern WHITESPACE_PATTERN = Pattern.compile(
"//p{javaWhitespace}+");
El concepto básico de hasNext () y hasNextLine () es
hasNextLine : - Devuelve verdadero si hay otra línea en la entrada de este escáner. Este método puede bloquearse mientras espera la entrada. El escáner no avanza más allá de ninguna entrada.
Devuelve: verdadero si y solo si este escáner tiene otra línea de entrada. Lanza: IllegalStateException - si este escáner está cerrado
hasNext
Devuelve verdadero si el siguiente token completo coincide con el patrón especificado.
Un token completo tiene el prefijo y el postfijo por entrada que coincida con el patrón delimitador. Este método puede bloquearse mientras espera la entrada. El escáner no avanza más allá de ninguna entrada.
Parámetros: patrón: el patrón para buscar
Devuelve: verdadero si y solo si este escáner tiene otra ficha que coincida con el patrón especificado
Desde su última entrada diciendo verdadero para nextLine () porque Una llamada a scan.nextLine (); devuelve el siguiente token. Es importante tener en cuenta que el escáner devuelve un espacio y una letra, porque está leyendo desde el final del último token hasta el comienzo de la siguiente línea.
Está consumiendo el valor de
next()
, pero solicita
hasNext()
y
hasNextLine()
.
next()
, por defecto, devuelve todo al siguiente
whitespace()
.
Entonces, está iterando a través de todas las cadenas separadas por espacios en blanco, y después de cada una de ellas está preguntando sobre
nextLine()
.
i 1 1
->
hasNextLine()
?
Cierto.
hasNext()
?
También es cierto
1 1
->
hasNextLine()
?
Cierto.
hasNext()
?
También es cierto (todavía queda un espacio en blanco)
1
->
hasNextLine()
?
Verdadero (separador de línea, probablemente).
haxNext?
Falso, ya no hay espacios en blanco.
La razón es que
hasNext()
comprueba si hay más caracteres disponibles que no sean espacios en blanco.
hasNextLine()
comprueba si hay otra línea de texto disponible.
Su archivo de texto probablemente tenga una nueva línea al final, por lo que tiene otra línea pero no más caracteres que no sean espacios en blanco.
Muchos editores de texto agregan automáticamente una nueva línea al final de un archivo si aún no hay una.
En otras palabras, su archivo de entrada no es este (los números son números de línea):
1. a 3 9
2. b 3 6
3. c 3 3
4. d 2 8
5. e 2 5
En realidad es esto:
1. a 3 9
2. b 3 6
3. c 3 3
4. d 2 8
5. e 2 5
6.