Java Scanner hasNext () vs. hasNextLine ()

1. Panoramica

La classe Scanner è uno strumento utile che può analizzare tipi e stringhe primitive utilizzando espressioni regolari ed è stata introdotta nel pacchetto java.util in Java 5.

In questo breve tutorial parleremo dei suoi metodi hasNext () e hasNextLine () . Anche se questi due metodi possono sembrare abbastanza simili all'inizio, in realtà stanno facendo controlli abbastanza diversi.

Puoi anche leggere di più sulla versatile classe Scanner nella guida rapida qui.

2. hasNext ()

2.1. Utilizzo di base

Il metodo hasNext () controlla se lo Scanner ha un altro token nel suo input. Uno Scanner suddivide il suo input in token utilizzando un modello delimitatore, che corrisponde agli spazi per impostazione predefinita. Cioè, hasNext () controlla l'input e restituisce true se ha un altro carattere diverso da uno spazio vuoto.

Dovremmo anche notare alcuni dettagli sul delimitatore predefinito:

  • Lo spazio vuoto include non solo il carattere spazio, ma anche tabulazione ( \ t ), avanzamento riga ( \ n ) e ancora più caratteri
  • I caratteri di spazi bianchi continui vengono trattati come un unico delimitatore
  • Le righe vuote alla fine dell'input non vengono stampate, ovvero hasNext () restituisce false per le righe vuote

Diamo un'occhiata a un esempio di come hasNext () funziona con il delimitatore predefinito. Per prima cosa, prepareremo una stringa di input per aiutarci a esplorare il risultato dell'analisi di 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();

Successivamente, analizziamo l'input e stampiamo il risultato:

Scanner scanner = new Scanner(INPUT); while (scanner.hasNext()) { log.info(scanner.next()); } log.info("--------OUTPUT--END---------") 

Se eseguiamo il codice sopra, vedremo l'output della console:

[DEMO]magic [DEMO]project [DEMO]database: [DEMO]oracle [DEMO]dependencies: [DEMO]spring:foo:bar [DEMO]--------OUTPUT--END--------- 

2.2. Con delimitatore personalizzato

Finora, abbiamo esaminato hasNext () con il delimitatore predefinito. Il dispositivo d'esplorazione di classe fornisce un'useDelimiter (string) metodo che ci permette di cambiare il delimitatore. Una volta modificato il delimitatore, il metodo hasNext () effettuerà il controllo con il nuovo delimitatore invece di quello predefinito.

Vediamo un altro esempio di come hasNext () e next () funzionano con un delimitatore personalizzato. Riutilizzeremo l'input dell'ultimo esempio.

Dopo lo scanner analizza un corrispondente segnalino la stringa “ dipendenze: “cambieremo il delimitatore di due punti ( :) in modo da poter analizzare ed estrarre ciascun valore delle dipendenze:

while (scanner.hasNext()) { String token = scanner.next(); if ("dependencies:".equals(token)) { scanner.useDelimiter(":"); } log.info(token); } log.info("--------OUTPUT--END---------");

Vediamo l'output risultante:

[DEMO]magic [DEMO]project [DEMO]database: [DEMO]oracle [DEMO]dependencies: [DEMO] spring [DEMO]foo [DEMO]bar [DEMO]--------OUTPUT--END---------

Grande! Abbiamo estratto con successo i valori in " dipendenze ", tuttavia, ci sono alcuni problemi di interruzione di riga imprevisti . Vedremo come evitarli nella prossima sezione.

2.3. Con regex come delimitatore

Rivediamo l'output nell'ultima sezione. Innanzitutto, abbiamo notato che è presente un'interruzione di riga ( \ n ) prima di " primavera ". Abbiamo cambiato il delimitatore in " : " dopo che il token "dipendenze:" è stato recuperato. L'interruzione di riga dopo le " dipendenze: " ora diventa la parte del token successivo. Pertanto, hasNext () ha restituito true e l'interruzione di riga è stata stampata.

Per lo stesso motivo, l'avanzamento riga dopo " ibernazione " e l'ultima riga vuota diventano la parte dell'ultimo token, quindi vengono stampate due righe vuote insieme a " ibernazione ".

Se possiamo impostare come delimitatori sia i due punti che gli spazi bianchi, i valori delle "dipendenze" verranno analizzati correttamente e il nostro problema verrà risolto. Per ottenere ciò, cambiamo la chiamata useDelimiter (":") :

scanner.useDelimiter(":|\\s+"); 

Il " : | \\ s + " qui è un'espressione regolare che corrisponde a un singolo ":" o uno o più spazi vuoti. Con questa correzione, l'output si trasforma in:

[DEMO]magic [DEMO]project [DEMO]database: [DEMO]oracle [DEMO]dependencies: [DEMO]spring [DEMO]foo [DEMO]bar [DEMO]--------OUTPUT--END---------

3. hasNextLine ()

Il metodo hasNextLine () verifica se è presente un'altra riga nell'input dell'oggetto Scanner , indipendentemente dal fatto che la riga sia vuota o meno.

Prendiamo di nuovo lo stesso input. Questa volta, aggiungeremo i numeri di riga davanti a ciascuna riga nell'input utilizzando i metodi hasNextLine () e nextLine () :

int i = 0; while (scanner.hasNextLine())  log.info(String.format("%d log.info("--------OUTPUT--END---------");

Ora, diamo un'occhiata al nostro output:

[DEMO]1|magic project [DEMO]2| database: oracle [DEMO]3|dependencies: [DEMO]4|spring:foo:bar [DEMO]5| [DEMO]--------OUTPUT--END---------

Come ci aspettavamo, vengono stampati i numeri di riga e anche l'ultima riga vuota.

4. Conclusione

In questo articolo, abbiamo imparato che Scanner s' hasNextLine) ( controlli metodo se c'è un'altra linea in ingresso, non importa se la linea è vuota o no, mentre hasNext () utilizza un delimitatore per verificare la presenza di un'altra token.

Come sempre, il codice sorgente completo per gli esempi è disponibile su GitHub.