Scanner 入力の全体像
Scanner は「テキストをトークン(単語・数値など)に分解して読み取る」ためのユーティリティです。標準入力(キーボード)だけでなく、文字列、ファイル、入力ストリームからも扱えます。最大の利点は「型別の読み取りメソッド(nextInt, nextDouble, nextLine など)」と「入力の有無を確認するメソッド(hasNextXXX)」を備えていて、初心者でも安全に使えることです。
基本の使い方と標準入力
標準入力から読み取る(最小例)
import java.util.Scanner;
public class ReadBasic {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in); // キーボード入力
System.out.print("年齢を入力: ");
int age = sc.nextInt(); // 数値トークンを取得
sc.nextLine(); // 改行を消費(後述の罠対策)
System.out.print("名前を入力: ");
String name = sc.nextLine(); // 1行まるごと取得
System.out.println("こんにちは " + name + "(" + age + "歳)");
sc.close(); // 明示的に閉じる(または try-with-resources)
}
}
Java- nextInt/nextDouble: 空白や改行で区切られた「数値トークン」を読みます。
- nextLine: 改行まで「1行全体」を読みます。
- close: 使い終わったら閉じるのが基本です。標準入力を閉じると再利用できないため、短いプログラムなら最後に閉じるか、明示的に閉じない選択も現実的です。
重要ポイントの深掘り:トークンと行の違い、nextLine の罠
トークン読み取りと行読み取りの違い
- トークン系(nextInt, next, nextDouble): 空白や改行で区切られた「次の単語」を返します。区切りは既定で空白類(スペース、タブ、改行)。
- 行系(nextLine): 改行までの「その行の残りすべて」を返します。空白も含みます。
この違いを意識して組み合わせることが重要です。
nextInt の後に nextLine が空振りする問題
nextInt() は数値だけを取り、行末の改行は残したままにします。続けて nextLine() を呼ぶと、その残った改行だけを読み取り「空文字」を返す、という事故がよく起きます。
int age = sc.nextInt();
String name = sc.nextLine(); // ← 直前の改行を読んでしまい、空文字になる
Java対策は「トークン系の後に行系を使う前に、改行を1回捨てる」ことです。
int age = sc.nextInt();
sc.nextLine(); // 改行のクリア
String name = sc.nextLine();
Javaまたは「常に行で受けてから、パースする」方式にすると安全です。
int age = Integer.parseInt(sc.nextLine().trim());
Java入力検証と安全な読み取り
hasNextXXX で存在確認
System.out.print("整数を入力: ");
if (sc.hasNextInt()) {
int n = sc.nextInt();
System.out.println("OK: " + n);
} else {
System.out.println("整数ではありません");
sc.nextLine(); // 誤入力の行を捨てる
}
Java- hasNextInt/hasNextDouble: 次トークンが指定型として読み取れるかを事前確認。
- hasNextLine: 次の行が存在するか。
例外を避ける安全入力ユーティリティ
static int readIntSafely(Scanner sc, String prompt) {
while (true) {
System.out.print(prompt);
if (sc.hasNextInt()) {
int v = sc.nextInt();
sc.nextLine(); // 改行クリア
return v;
} else {
System.out.println("整数を入力してください。");
sc.nextLine(); // 誤入力を破棄
}
}
}
Java「存在確認 → 誤入力を破棄 → 再入力」をひとまとめにすると、対話入力が安定します。
デリミタ、ロケール、文字コード(実務で効く設定)
区切り文字(デリミタ)の変更
Scanner sc = new Scanner("10,20,30");
sc.useDelimiter(","); // カンマ区切りに変更
while (sc.hasNextInt()) {
System.out.println(sc.nextInt()); // 10 20 30
}
sc.close();
JavaCSV の一部処理や特殊な区切りに便利です。複雑な CSV は専用ライブラリを検討しましょう。
ロケールで小数点や数字書式を合わせる
Scanner sc = new Scanner("3,14");
sc.useLocale(java.util.Locale.GERMANY); // ドイツでは小数点が「,」
System.out.println(sc.nextDouble()); // 3.14
Java小数点記号が国によって違う場合は useLocale で整合を取ります。
文字コード(ファイル・ストリーム入力)
import java.nio.charset.StandardCharsets;
import java.io.File;
import java.util.Scanner;
try (Scanner sc = new Scanner(new File("data.txt"), StandardCharsets.UTF_8)) {
while (sc.hasNextLine()) System.out.println(sc.nextLine());
}
Java日本語テキストなどは文字コードを明示すると文字化けを防げます。
リソース管理とファイル入力
try-with-resources で安全に閉じる
import java.util.Scanner;
import java.io.File;
public class ReadFile {
public static void main(String[] args) throws Exception {
try (Scanner sc = new Scanner(new File("input.txt"))) {
while (sc.hasNextLine()) {
String line = sc.nextLine();
System.out.println("read: " + line);
}
} // 自動で close
}
}
Java- ファイル/ネットワーク入力: 必ず
try-with-resourcesを使う。例外時でも確実に閉じられます。 - 標準入力: アプリの最後で閉じるか、短命プログラムなら未 close でも実害は少ないです(ただしライブラリや長寿命プロセスでは明示的に管理)。
例題で身につける
例 1: 1行ずつ読み、空行で終了
import java.util.Scanner;
public class UntilBlank {
public static void main(String[] args) {
try (Scanner sc = new Scanner(System.in)) {
System.out.println("空行で終了。入力してください:");
while (true) {
String line = sc.nextLine();
if (line.isBlank()) break;
System.out.println("echo: " + line.trim());
}
}
}
}
Java例 2: 整数リストを読み、合計を出す(安全版)
import java.util.Scanner;
public class SumInts {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int sum = 0;
System.out.println("整数をスペース区切りで入力(非整数は無視、改行で終了):");
while (sc.hasNext()) {
if (sc.hasNextInt()) sum += sc.nextInt();
else sc.next(); // 非整数トークンを捨てる
}
System.out.println("sum=" + sum);
sc.close();
}
}
Java例 3: 行で受けてからパース(nextLine 方式)
import java.util.Scanner;
public class ParseLine {
public static void main(String[] args) {
try (Scanner sc = new Scanner(System.in)) {
System.out.print("価格を入力(整数): ");
int price = Integer.parseInt(sc.nextLine().trim());
System.out.print("税率を入力(例 0.1): ");
double tax = Double.parseDouble(sc.nextLine().trim());
System.out.println("税込=" + Math.round(price * (1 + tax)));
}
}
}
Java仕上げのアドバイス(重要部分のまとめ)
- トークン系(nextInt/next)と行系(nextLine)の違いを理解し、混在時は「改行クリア」か「行→パース」に統一する。
- hasNextXXX で入力検証し、誤入力は破棄して再入力を促す。例外を前提にしない設計が初心者にも安全。
- 区切り(useDelimiter)、ロケール(useLocale)、文字コード(コンストラクタの charset)を明示すると、国際化やファイル入力で安定する。
- リソースは
try-with-resourcesで確実に閉じる。標準入力は最後に閉じるか、短命なら無理に閉じない。 - 大量データや高速処理が必要なら
BufferedReader+手動パースも検討し、Scanner は「簡単で安全」を優先する場面で使う。
