انتقل إلى المحتوى
أمين أبوزيد
منشورBEG-011-L01

قراءة المدخلات باستخدام Scanner

  • الدرس 1 من 6
  • 13 دقيقة قراءة
  • مبتدئ
في هذا الدرس 11 موضوعات

هذا الدرس متاح حاليًا باللغة الإنجليزية فقط، ولم تُنشر نسخته العربية بعد.

Lesson Overview

So far your programs have only talked: they print a result and stop. Every program ran the same way every time, because you typed all of its data into the source code. In this module the program starts to listen. It asks a question, waits for the user to type, and uses the answer.

Think of a shop counter. The cashier asks "What would you like?", the customer answers, the cashier checks the answer, and finally prints a receipt. Over six lessons you will build that whole counter: ask, check, print. This first lesson is the ask part. You will learn the class Java provides for reading what a user types on the keyboard: Scanner.

Why this matters: a program that cannot receive data is a calculator with the numbers glued on. Backend services spend their whole life receiving input, whether from a keyboard, a file, or a web request. The tool changes later, but the habit is the same one you learn here: create a reader, prompt, read, use the value.

This lesson builds on BEG-009 (variables, String, double, int) and BEG-010 (expressions). It assumes you can compile and run a program from your IDE or terminal.

Learning Objectives

By the end of this lesson you will be able to:

  • Import java.util.Scanner and create one that reads from the keyboard.
  • Read a line of text with nextLine(), a single word with next(), a whole number with nextInt(), and a decimal with nextDouble().
  • Print a prompt first so the user knows what to type.
  • Explain the difference between reading a line and reading a token.
  • Predict what the program does when the user types something that does not match the method you called (it stops with an error; fixing that is the subject of later lessons).
  • Explain what close() does for a keyboard scanner and when to use it.

Written Explanation

Where the keyboard lives: System.in

You already know System.out, the place a program prints to. Its twin is System.in, the place a program reads from. By default, System.in is connected to the keyboard (strictly, to standard input; when you run a program in a terminal you can redirect it from a file or another program). System.in is a low-level stream of raw bytes, awkward to use directly. Scanner wraps it and turns the raw input into text, numbers, and lines.

Three lines to get started

java
import java.util.Scanner;                 // 1. make the class available

public class Greeter {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);   // 2. create a scanner on the keyboard
        // ... use it ...
    }
}
  1. import java.util.Scanner; goes at the top of the file, before the class. Scanner lives in the package java.util, and Java only finds classes from that package when you import them. (Classes in java.lang, such as String and System, are imported automatically.)
  2. new Scanner(System.in) builds a scanner attached to the keyboard. The variable in is a reference variable, like the String variables from BEG-009: the box holds a pointer to a Scanner object. in is just a name; scanner or input are equally common.

You create the scanner once and reuse it for the whole program. Creating several scanners on the same System.in is a classic way to lose input, because each one may read ahead and hold characters the others never see.

Prompt, then read

A running program that waits silently looks frozen. Always print a prompt first, using print (not println) so the cursor stays on the same line:

java
System.out.print("Your name: ");
String name = in.nextLine();

The program stops at nextLine() until the user types something and presses Enter. This pause is called blocking: the program is waiting for input and does nothing else.

The four reading methods

MethodReadsReturns
nextLine()Everything up to the end of the line (Enter)String, without the Enter
next()One word (a token, stopped by whitespace)String
nextInt()The next token, as a whole numberint
nextDouble()The next token, as a decimal numberdouble

There are siblings for the other primitive types (nextLong(), nextBoolean(), and so on). These four are enough for now.

The Javadoc says Scanner breaks its input into tokens using a delimiter, and that by default the delimiter is whitespace: spaces, tabs, and line endings. So next(), nextInt(), and nextDouble() each skip any whitespace in front of them, read one token, and stop right after it. nextLine() works differently: it returns whatever is left on the current line, spaces included, and moves to the start of the next line.

The difference matters as soon as the text has a space in it:

User typesnext() returnsnextLine() returns
AnaAnaAna
Ana SmithAna (and Smith is still waiting)Ana Smith

So for names, addresses, and sentences use nextLine(). For single numbers use nextInt() or nextDouble().

What a number reader needs

nextInt() accepts only text that looks like a whole number, for example 7, -3, or +5. If the user types abc, or 3.5, or a number too large for an int, Java throws an InputMismatchException and the program stops. Exceptions have their own module later. For this lesson, remember the rule: call the method that matches what you expect, and the user must play along. Lessons 3 and 5 show how to survive users who do not.

nextDouble() has a quirk worth knowing early. It reads numbers using the locale of the computer, meaning the language and region settings. On a machine set up with a dot as the decimal separator, 2.5 works and 2,5 throws. On a machine set up with a comma, it can be the other way round. If your decimals are rejected on your own computer, this is the first thing to suspect.

Closing the scanner

in.close() tells the scanner you are done. For a scanner attached to System.in there is a catch the Javadoc points out: closing a scanner closes the underlying source if it can be closed, and System.in can. After that, nothing in the program can read the keyboard again, even through a new Scanner. So the rule is: create one scanner, use it for the whole program, and close it at the very end (or, in small exercises, simply let the program finish). Never close it in the middle and then try to read again.

The anatomy of a small input program

text
1. import java.util.Scanner;
2. create the scanner once
3. for each question: print a prompt, read, store in a variable
4. use the variables (calculate, print)
5. close the scanner

Every program in this module follows this pattern.

Examples

Example 1: a greeter (simple)

java
import java.util.Scanner;

public class Greeter {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.print("Your name: ");
        String name = in.nextLine();
        System.out.println("Hi, " + name + "! Your name has " + name.length() + " characters.");
        in.close();
    }
}

Run with the user typing Ana Smith (shown after the prompt):

text
Your name: Ana Smith
Hi, Ana Smith! Your name has 9 characters.

name.length() counts the space too, giving 9. The value that the user typed is now an ordinary String, and everything from BEG-009 applies to it.

Example 2: mixing text and numbers (practical)

A print shop charges by area. Ask for the width, the height, and how many copies:

java
import java.util.Scanner;

public class Rect {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.print("Width in cm: ");
        double width = in.nextDouble();
        System.out.print("Height in cm: ");
        double height = in.nextDouble();
        System.out.print("Copies: ");
        int copies = in.nextInt();
        System.out.println("Total area: " + (width * height * copies) + " square cm");
        in.close();
    }
}

With the user typing 2.5, 4, 3 on three separate lines:

text
Width in cm: 2.5
Height in cm: 4
Copies: 3
Total area: 30.0 square cm

Two things to notice. nextDouble() accepts 4 and gives 4.0, since a whole number is a valid decimal. And the prompts and the user's text share the screen, so the terminal shows them on one line each. If the user types abc for the width instead, the program stops with this message (the first line of the stack trace; the rest is trimmed here):

text
Width in cm: Exception in thread "main" java.util.InputMismatchException
	at java.base/java.util.Scanner.throwFor(Scanner.java:947)

The same happens on my test machine for 2,5, because its locale expects a dot.

Example 3: one word or one line? (realistic)

Imagine a form where a clerk types a customer's full name. What happens if the programmer uses next()?

java
import java.util.Scanner;

public class Tokens {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.print("Full name: ");
        String first = in.next();
        System.out.println("next() gave: [" + first + "]");
        String rest = in.nextLine();
        System.out.println("nextLine() gave: [" + rest + "]");
    }
}

With the user typing Ana Maria Smith:

text
Full name: Ana Maria Smith
next() gave: [Ana]
nextLine() gave: [ Maria Smith]

next() took only the first word. The rest of the line, including the space after Ana, was still waiting for the next read. The square brackets in the output make the leading space visible. This "leftover" idea is the key to the next lesson.

Backend Insight

A backend service is a program that reads input all day. Real servers do not use a keyboard Scanner: a web server receives bytes from a network connection, and a framework converts them into objects. But the shape is the same:

  1. Something arrives as raw text.
  2. The program must pick the right reader for the expected shape (a line, a number, a date).
  3. If the input does not match, the program must decide what to do: crash, or answer with an error message.

The crash in Example 2 is the key habit to unlearn early. A command-line program that dies on abc is merely annoying. A web service that dies on a malformed request lets one bad caller take down service for everyone. Later modules show how to turn bad input into a polite answer. Notice also that Scanner can read from other sources than the keyboard: it can wrap a file or a string, so skills from this lesson carry over.

Common Mistakes

Mistake 1: Forgetting the import

java
Scanner in = new Scanner(System.in);   // error without the import line

The compiler reports that it cannot find the symbol Scanner. Add import java.util.Scanner; at the top of the file, above the class.

Mistake 2: Reading without a prompt

A program that prints nothing and waits looks hung. Always print what you expect, and which units or format you want ("Width in cm:").

Mistake 3: Using next() for text with spaces

next() returns one word. A full name, an address, or a sentence needs nextLine(), as Example 3 shows.

Mistake 4: Creating a new Scanner for every question

  • Incorrect: a new Scanner(System.in) before each question.
  • Correct: one scanner, created once, passed through the whole program.

Extra scanners on one keyboard may each buffer more input than they use, so some typed text goes missing, and closing any of them closes System.in for all.

Mistake 5: Assuming the user will type what you asked for

nextInt() on abc stops the program. Later lessons cover this; for now, the point is that the user is a separate, unpredictable party.

Exercises

Try each exercise yourself before opening the solutions.

Level A: Foundation

A1. Which line must appear at the top of a file that uses Scanner? Why is no such line needed for String?

أظهر الحل A1

A1. import java.util.Scanner;. String belongs to the package java.lang, which Java imports automatically for every file.

A2. Which method would you call to read each of these: (a) a city name that may be "New York"; (b) the number of passengers; (c) a temperature such as 21.5?

أظهر الحل A2

A2. (a) nextLine(), because the name has a space. (b) nextInt(). (c) nextDouble().

A3. What does the user see if the program calls in.nextLine() without printing anything first? Why is that a problem?

أظهر الحل A3

A3. The cursor just sits there with no hint, so the user cannot tell whether the program has frozen or what it wants. A prompt printed with print fixes that.

Level B: Application

B1. Write a program that asks for a city and a country (each may have spaces) and prints You live in <city>, <country>.

أظهر الحل B1

B1.

java
import java.util.Scanner;

public class Where {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.print("City: ");
        String city = in.nextLine();
        System.out.print("Country: ");
        String country = in.nextLine();
        System.out.println("You live in " + city + ", " + country + ".");
        in.close();
    }
}

B2. Write a program that asks for two decimals and prints their sum and average.

أظهر الحل B2

B2. Read both with nextDouble() into x and y, then print x + y and (x + y) / 2. Because both variables are double, the average keeps its decimals; there is no integer-division problem here. (I did not compile B2 or B1 separately; both follow the pattern of the compiled examples above.)

B3. The user types Rosa Maria at the prompt and the program calls next() and then next() again, storing the results in a and b. What are a and b? What if it calls next() then nextLine()?

أظهر الحل B3

B3. With next() twice, a is Rosa and b is Maria. With next() then nextLine(), a is Rosa and the second variable is Maria with a leading space.

Level C: Challenge

C1. Write a program that asks for a product name (a line), a price (a decimal), and a quantity (a whole number), then prints a single summary line such as 3 x Pen at 1.5 = 4.5. Run it and note whether the quantity prompt is skipped. (Reading the name first, then two numbers, is safe: the next lesson explains when it is not.)

أظهر الحل C1

C1. Read the name with nextLine(), then nextDouble() for the price, then nextInt() for the quantity, then print qty + " x " + name + " at " + price + " = " + (qty * price). The quantity prompt is not skipped, because the trap only appears when a nextLine() comes after a number read. Lesson 2 explains it.

C2. Explain what goes wrong if a program creates Scanner a = new Scanner(System.in), uses it, calls a.close(), and then creates Scanner b = new Scanner(System.in) and calls b.nextLine().

أظهر الحل C2

C2. Closing a also closes System.in, the keyboard stream underneath. The new scanner b then has nothing to read from, so reading fails (the Javadoc describes operations on a closed scanner failing; the exact exception for this case depends on the stream). Create one scanner and close it only at the end.

Mini Challenge

Write Business card asker. The program asks for a name (line), a job title (line), and a phone number (read as a line, since phone numbers are not for arithmetic), then prints a small card using the printing techniques from BEG-008:

text
+--------------------------+
 Ana Smith
 Backend Developer
 Tel: 555-0100
+--------------------------+

Check your work: the name and title can contain spaces; every question has a prompt; there is exactly one Scanner; and you can say why the phone number is a String rather than an int.

Summary & Next Lesson

Key takeaways

  • import java.util.Scanner;, then new Scanner(System.in) once, give you a reader for the keyboard.
  • nextLine() reads a whole line. next() reads one word. nextInt() and nextDouble() read numbers.
  • Print a prompt with print before every read.
  • A number reader throws an error on text that is not a number. The program must guard against that, which later lessons teach.
  • Close the scanner once at the end. Closing it also closes System.in.

Next lesson

The next lesson, "The nextInt / nextLine trap", shows the most famous Scanner bug: ask for a number and then for a line of text, and the text question gets skipped. You will see why it happens and how to fix it.

Self-check

  1. Which import line does Scanner need?
  2. Which method reads a full name such as "Ana Smith"?
  3. What does next() return when the user types Ana Smith?
  4. Why print a prompt before reading?
  5. Why should you create only one Scanner on the keyboard?
أظهر الإجابات
  1. import java.util.Scanner;
  2. nextLine().
  3. Ana. The rest of the line is still waiting in the input.
  4. Without a prompt the user cannot tell that the program is waiting, or what it expects.
  5. Extra scanners may each hold typed input the others never see, and closing any of them closes System.in for all.

References

  • Oracle, Java SE 21 API, Scanner. Supports the default whitespace delimiter, the behaviour of nextLine(), InputMismatchException for tokens that do not match, locale-dependent number parsing, and the fact that closing a scanner closes a closeable source such as System.in.
  • Code in the examples was compiled and run with JDK 21 on the course author's machine; the quoted outputs are the real outputs. Statements that System.in is a keyboard-connected stream and that several scanners can lose input are summarised from the Javadoc's description of closing and buffering and are best treated as practical guidance rather than a quotation.

التطبيق

طبّق هذا الدرس بمختبر الوحدة وتمارينها واختبارها.

المختبر والتمارين الاختبار

تعليم الدرس كمكتمل اختياري ويمكنك التراجع عنه في أي وقت. يبقى تقدمك محفوظًا في هذا المتصفح.

اكتب للبحث في المستويات والمراحل والوحدات والدروس.