Når en lager enkle, interaktive programmer har en ofte behov for å lese inn linjer med tekst og konvertere deler av teksten til ulike typer tall, logiske verdier osv. Dette er et eksempel på det som kalles parsing, dvs. oppstykking av tekst i deler og tolkning av delene. For enkel input er Scanner-klassen veldig hendig, siden den håndterer både oppstykking av teksten i deler og konvertering til de vanligste datatypene.
Instansiering av Scanner
En Scanner instansieres ved å gi den en InputStream (f.eks. System.in), String eller File, som argument:
Scanner scanner = new Scanner(System.in); // antar her at en har lagt inn import java.util.Scanner; øverst i fila under pakke-deklarasjonen
Dette betyr at du kan bruke den til å lese tekst fra andre tekstkilder også, men fokuset her er input fra brukeren gjennom System.in.
Når Scanner'en er instansiert kan du gjøre essensielt to ting:
- Spørre om det venter input av en bestemt type, f.eks. linje, tall eller logisk verdi, med en av mange hasNext-metoder, f.eks. hasNextLine, hasNextInt, hasNextBoolean, osv. Disse metodene returnerer alle true, dersom input'en som venter passer til typen verdi.
- Lese/konsumere input av en bestemt type., med tilsvarende next-metoder, f.eks. nextLine, nextInt, nextBoolean, osv. Disse returnerer en verdi av angitt type, f.eks. vil nextInt returnere int og nextLine returnere String osv.
Innlesing
Anta f.eks. at du ønsker å lese inn et koordinat-par (int) og en logisk verdi (boolean). Da kan du typisk skrive følgende kode:
// antar at scanner-variablen allerede er instansiert som over og at en har skrevet ut ledetekst til brukeren int x = scanner.nextInt(); int y = scanner.nextInt(); boolean b = scanner.nextBoolean();
Dersom brukeren så skriver inn en linje med tekst, f.eks. "0 42 true" (uten anførselstegnene), så vil x bli satt til 0, y bli satt til 42 og b til true. Hvis en derimot skriver inn "true 0 42" så vil programmet kræsje, fordi true ikke kan leses som en int. Det er derfor avgjørende at brukeren vet hva som forventes som input.
Sjekk av type input
I noen tilfeller er det praktisk at koden som leser input er litt fleksibel, dvs. kan tillate og tolke input av med litt varierende type innhold. Da bruker en hasNext-metodene til å sjekke typen input, før en faktisk leser og tilordner. Anta f.eks. at en skal lese inn en blanding av tall og matematiske operatorer som +, -, * og /. Da kan en legge inn følgende kode for sjekk og innlesing:
// fortsett så lenge det er mer input while (scanner.hasNext()) { // sjekk om input'en faktisk følger double-syntaksen if (scanner.hasNextDouble()) { double operand = scanner.nextDouble(); // gjør noe med operand her // ... } else { // hvis input'en ikke er en double, er det ihvertfall et ord/token String operator = scanner.next(); // gjør noe med operator-verdien her // ... } }
Anta at brukeren har skrevet inn "1.0 + 2" (uten anførselstegn). I den første runden i while-løkka vil den første grenen av if'en bli kjørt og operand bli tilordnet 1.0, fordi "1.0" jo følger double-syntaks og hasNextDouble()-metoden derfor returnerer true. I den andre runden vil den andre grenen av if'en bli kjørt og operator blir tilordnet "+" fordi "+" ikke er gyldig iht. double-syntaks. I den tredje runden blir den første grenen kjørt igjen fordi "2" kan leses som en double. Merk imidlertid at det går galt dersom brukeren skriver inn "1.0+2", fordi reglene for oppstykking gjør at dette regnes som én input og ikke tre.
Oppstykking av input
Tolkingen av input foregår egentlig i to trinn.
- Først deles input'en opp i deler, såkalte tokens, ved at Scanner'en leser tegn for tegn inntil den kommer til skilletegn.
- og så tolkes delene som int, double, boolean eller bare som String, avhengig av hvilke av hasNext- eller next-metodene en kaller.