xSKILLby Infirals
Register

Java for Beginners

0 of 24 notes read 0%

Reading progress is saved to your INFIRALS account. Sign in to keep this note marked as read.

Reading input with Scanner

Exceptions, collections and modern Java11 min readLesson 3 of 6

3.1 Reading tokens

Scanner reads text and converts tokens to values. Create it with a source: new Scanner(System.in) for the keyboard, a String for testing, or a Path for a file. The class is in java.util, so it needs an import.

next() returns the next token as a String. nextInt(), nextDouble(), and nextBoolean() parse the next token as that type. Tokens are separated by whitespace by default.

hasNext() reports whether another token exists. hasNextInt() checks the next token before parsing, which avoids an exception on bad input. Use the check when the source may contain unexpected text.

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner("Asha 16 92");
        String name = scanner.next();
        int age = scanner.nextInt();
        int score = scanner.nextInt();
        System.out.println(name + " " + age + " " + score);
        scanner.close();
    }
}

Output

Asha 16 92

3.1.1 The nextLine trap

nextInt() reads a token and leaves the rest of the line, including the line break, in the buffer. A following nextLine() returns the remaining part of that line, often an empty string. The name that was supposed to be read next stays in the buffer.

Read the leftover line after nextInt() when the next value is a full line. Another option is to read every value with nextLine() and parse it with Integer.parseInt. Choose one style and keep it through the input section.

This behavior follows from token reading. A token ends before the whitespace, so the whitespace is not consumed as part of the number.

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner("""
                16
                Asha
                """);
        int age = scanner.nextInt();
        String leftover = scanner.nextLine();
        String name = scanner.nextLine();
        System.out.println("Age " + age);
        System.out.println("Leftover length " + leftover.length());
        System.out.println("Name " + name);
    }
}

Output

Age 16
Leftover length 0
Name Asha

3.1.2 Validating input

hasNextInt() returns true only when the next token can be parsed as an integer. A loop can skip or report bad tokens without crashing. InputMismatchException is thrown when a parse method is called on text that does not match.

A validation loop asks again while the value is outside a range. With System.in, the loop needs a prompt, but the structure is the same: read, check, repeat.

A message should say what is accepted. Printing the expected range and type helps the person at the keyboard more than printing an exception class.

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner("12 x 7 30");
        int total = 0;
        while (scanner.hasNext()) {
            if (scanner.hasNextInt()) {
                total += scanner.nextInt();
            } else {
                System.out.println("Skipped: " + scanner.next());
            }
        }
        System.out.println("Total: " + total);
    }
}

Output

Skipped: x
Total: 49

3.1.3 Files and closing

A Scanner can read a file: new Scanner(Path.of("data.txt")). The constructor throws IOException, a checked exception, so the method must declare it or use try-with-resources.

Close a Scanner when it reads a file or a string. A Scanner on System.in wraps a shared stream. Closing it also closes the stream for the rest of the program, so many programs leave it open.

Try-with-resources is the clean way to close a file scanner. The reader closes at the end of the block, even if parsing fails.

java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) throws IOException {
        Path file = Path.of("scores.txt");
        Files.writeString(file, "80 90 70");
        try (Scanner scanner = new Scanner(file)) {
            int total = 0;
            while (scanner.hasNextInt()) {
                total += scanner.nextInt();
            }
            System.out.println(total);
        }
    }
}

Output

240

3.1.4 Splitting and parsing

Scanner reads tokens; String.split cuts a line on a delimiter. Both have a place. Use split when a line has a known format such as comma-separated values. Use Scanner when values are separated by whitespace and mixed types matter.

Integer.parseInt converts a trimmed string to an int. Double.parseDouble does the same for decimals. Wrap the parse in a try/catch only when the text may be invalid and the program can recover.

Keep the input rules in one method when several prompts share them. That method returns a value that has passed the checks, so the rest of the program can use it without repeating validation.

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner("Ravi 78");
        String name = scanner.next();
        int score = scanner.nextInt();
        String band = score >= 75 ? "distinction" : "pass";
        System.out.println(name + ": " + band);
        scanner.close();
    }
}

Output

Ravi: distinction

3.1.5 Practice

  1. Read a name and two integers from a string with Scanner and print their sum.
  2. Reproduce the nextInt and nextLine behavior with 16 followed by Asha on the next line.
  3. Loop over "12 x 7 30" and skip non-integers, printing the total.
  4. Write a file with three numbers, read it with Scanner, and print the sum.
  5. Read a name and score, then print the score band.

For step 2, print the length of the leftover line. A length of 0 shows that the line break was consumed by the next call.

Interview questions

3 questions from this note. Open one to see the answer; no account needed.

  • 01Why does `nextLine()` return an empty string after `nextInt()`?

    `nextInt()` consumes the number but not the line break. The next `nextLine()` reads the remainder of that line, which is empty.

  • 02How do you check input before parsing?

    Use `hasNextInt()` or `hasNextDouble()`, or read a line and use `Integer.parseInt` inside a try/catch when recovery is possible.

  • 03Should a Scanner on `System.in` be closed?

    Usually not. Closing it closes the shared input stream, so later reads in the same program fail. Close file scanners instead, preferably with try-with-resources.