1. Información general
La clase Scanner es una herramienta útil que puede analizar tipos primitivos y cadenas utilizando expresiones regulares y se introdujo en el paquete java.util en Java 5.
En este breve tutorial, hablaremos sobre sus métodos hasNext () y hasNextLine () . Aunque estos dos métodos pueden parecer bastante similares al principio, en realidad están haciendo comprobaciones bastante diferentes.
También puede leer más sobre la clase de escáner versátil en la guía rápida aquí.
2. hasNext ()
2.1. Uso básico
El método hasNext () comprueba si el escáner tiene otro token en su entrada. Un escáner divide su entrada en tokens utilizando un patrón delimitador, que coincide con los espacios en blanco de forma predeterminada. Es decir, hasNext () comprueba la entrada y devuelve verdadero si tiene otro carácter que no sea un espacio en blanco.
También debemos tener en cuenta algunos detalles sobre el delimitador predeterminado:
- El espacio en blanco incluye no solo el carácter de espacio, sino también el espacio de tabulación ( \ t ), el salto de línea ( \ n ) e incluso más caracteres
- Los caracteres de espacio en blanco continuos se tratan como un solo delimitador
- Las líneas en blanco al final de la entrada no se imprimen, es decir, hasNext () devuelve falso para las líneas en blanco
Echemos un vistazo a un ejemplo de cómo funciona hasNext () con el delimitador predeterminado. Primero, prepararemos una cadena de entrada para ayudarnos a explorar el resultado del análisis sintáctico de S canner :
String INPUT = new StringBuilder() .append("magic\tproject\n") .append(" database: oracle\n") .append("dependencies:\n") .append("spring:foo:bar\n") .append("\n") // Note that the input ends with a blank line .toString();
A continuación, analicemos la entrada e imprimamos el resultado:
Scanner scanner = new Scanner(INPUT); while (scanner.hasNext()) { log.info(scanner.next()); } log.info("--------OUTPUT--END---------")
Si ejecutamos el código anterior, veremos el resultado de la consola:
[DEMO]magic [DEMO]project [DEMO]database: [DEMO]oracle [DEMO]dependencies: [DEMO]spring:foo:bar [DEMO]--------OUTPUT--END---------
2.2. Con delimitador personalizado
Hasta ahora, hemos visto hasNext () con el delimitador predeterminado. El escáner clase proporciona una useDelimiter (Patrón de encordado) método que nos permite cambiar el delimitador. Una vez que se cambia el delimitador, el método hasNext () hará la verificación con el nuevo delimitador en lugar del predeterminado.
Veamos otro ejemplo de cómo funcionan hasNext () y next () con un delimitador personalizado. Reutilizaremos la entrada del último ejemplo.
Después de que el escáner analiza un juego de contadores al “cadena de dependencias: “, vamos a cambiar el delimitador de dos puntos ( :) para que podamos analizar y extraer cada valor de las dependencias:
while (scanner.hasNext()) { String token = scanner.next(); if ("dependencies:".equals(token)) { scanner.useDelimiter(":"); } log.info(token); } log.info("--------OUTPUT--END---------");
Veamos la salida resultante:
[DEMO]magic [DEMO]project [DEMO]database: [DEMO]oracle [DEMO]dependencies: [DEMO] spring [DEMO]foo [DEMO]bar [DEMO]--------OUTPUT--END---------
¡Excelente! Hemos extraído con éxito los valores en " dependencias ", sin embargo, hay algunos problemas inesperados de saltos de línea . Veremos cómo evitarlos en la siguiente sección.
2.3. Con expresiones regulares como delimitador
Repasemos el resultado en la última sección. Primero, notamos que hay un salto de línea ( \ n ) antes de " primavera ". Hemos cambiado el delimitador a " : " después de que se obtuvo el token "dependencias:" . El salto de línea después de las " dependencias: " ahora se convierte en parte del siguiente token. Por lo tanto, hasNext () devolvió verdadero y se imprimió el salto de línea.
Por la misma razón, el avance de línea después de " hibernar " y la última línea en blanco se convierten en parte del último token, por lo que se imprimen dos líneas en blanco junto con " hibernar ".
Si podemos hacer dos puntos y espacios en blanco como delimitadores, entonces los valores de las "dependencias" se analizarán correctamente y nuestro problema se resolverá. Para lograr eso, cambiemos la llamada useDelimiter (“:”) :
scanner.useDelimiter(":|\\s+");
El " : | \\ s + " aquí es una expresión regular que coincide con un solo ":" o uno o más caracteres de espacio en blanco. Con esta solución, la salida se convierte en:
[DEMO]magic [DEMO]project [DEMO]database: [DEMO]oracle [DEMO]dependencies: [DEMO]spring [DEMO]foo [DEMO]bar [DEMO]--------OUTPUT--END---------
3. hasNextLine ()
El método hasNextLine () comprueba si hay otra línea en la entrada del objeto Scanner , sin importar si la línea está en blanco o no.
Tomemos la misma entrada nuevamente. Esta vez, agregaremos números de línea delante de cada línea en la entrada usando los métodos hasNextLine () y nextLine () :
int i = 0; while (scanner.hasNextLine()) log.info(String.format("%d log.info("--------OUTPUT--END---------");
Ahora, echemos un vistazo a nuestro resultado:
[DEMO]1|magic project [DEMO]2| database: oracle [DEMO]3|dependencies: [DEMO]4|spring:foo:bar [DEMO]5| [DEMO]--------OUTPUT--END---------
Como esperábamos, los números de línea se imprimen y la última línea en blanco también está allí.
4. Conclusión
En este artículo, hemos aprendido que Escáner 's hasNextLine () método comprueba si hay otra línea de la entrada, no importa si la línea está en blanco o no, mientras que hasNext () utiliza un delimitador para comprobar si hay otra ficha.
Como siempre, el código fuente completo de los ejemplos está disponible en GitHub.