Read line with Scanner

Learn read line with scanner with practical examples, diagrams, and best practices. Covers java, java.util.scanner, readline development techniques with visual explanations.

Mastering Line-by-Line Input with Java's Scanner Class

Hero image for Read line with Scanner

Learn how to effectively read and process input line by line using the java.util.Scanner class, covering common pitfalls and best practices.

The java.util.Scanner class is a versatile tool for parsing primitive types and strings using regular expressions. While it's commonly used for reading individual tokens (words), its ability to read entire lines of input is crucial for many applications, from command-line interfaces to file processing. This article will guide you through the proper use of Scanner for line-based input, highlighting key methods and potential issues.

Understanding Scanner.nextLine()

The primary method for reading an entire line of input with Scanner is nextLine(). This method reads input until it encounters a line separator (like \n or \r\n), consumes that separator, and returns the rest of the line as a String. It's important to understand that nextLine() consumes the line separator, which can be a source of common errors when mixed with other Scanner methods.

import java.util.Scanner;

public class ReadLineExample {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("Enter your full name: ");
        String fullName = scanner.nextLine();
        System.out.println("Hello, " + fullName + "!");

        System.out.print("Enter your favorite quote (press Enter when done): ");
        String quote = scanner.nextLine();
        System.out.println("Your quote: \"" + quote + "\"");

        scanner.close();
    }
}

Basic usage of Scanner.nextLine() to read full lines of text.

The nextLine() Trap: Mixing with next() Methods

A very common issue arises when nextLine() is used immediately after other Scanner methods like nextInt(), nextDouble(), or next(). These methods read a token but do not consume the trailing newline character. When nextLine() is called subsequently, it immediately consumes this leftover newline character and returns an empty string, skipping the intended line input. This is often referred to as the 'newline trap'.

flowchart TD
    A[Start Program] --> B{Call nextInt()};;
    B --> C[User enters '123' + Enter];;
    C --> D{nextInt() reads '123'};;
    D --> E["Newline character (\n) remains in buffer"];;
    E --> F{Call nextLine()};;
    F --> G["nextLine() consumes remaining \n"];;
    G --> H[Returns empty string];;
    H --> I[Program continues, skipping intended input];;
    I --> J[End Program];;

Illustrating the 'newline trap' when mixing nextInt() and nextLine().

import java.util.Scanner;

public class NewlineTrapExample {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("Enter your age: ");
        int age = scanner.nextInt(); // Reads integer, leaves newline
        System.out.println("You are " + age + " years old.");

        // PROBLEM: nextLine() will consume the leftover newline from nextInt()
        System.out.print("Enter your city: ");
        String city = scanner.nextLine(); // This will likely be empty!
        System.out.println("Your city is: " + city);

        scanner.close();
    }
}

Demonstration of the newline trap, where nextLine() reads an empty string.

Resolving the Newline Trap

The solution to the newline trap is simple: always consume the leftover newline character after calling any next() method (e.g., nextInt(), nextDouble(), next()) if you intend to call nextLine() immediately afterward. You can do this by adding an extra scanner.nextLine() call, which will simply discard the newline.

import java.util.Scanner;

public class NewlineTrapSolution {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("Enter your age: ");
        int age = scanner.nextInt(); // Reads integer, leaves newline
        scanner.nextLine(); // Consume the leftover newline character
        System.out.println("You are " + age + " years old.");

        System.out.print("Enter your city: ");
        String city = scanner.nextLine(); // Now this will read the actual city
        System.out.println("Your city is: " + city);

        scanner.close();
    }
}

Corrected code to handle the newline trap by adding an extra nextLine() call.