Javaにおける標準入力とは
標準入力とは、キーボードや実行環境の入力欄など、プログラムの外部からデータを受け取るための入り口のことです。
プログラムに値を渡す方法はいくつかありますが、標準入力を使うと、ソースコードを書き換えることなく、実行のたびに異なるデータをプログラムに与えられます。
標準入力を使うと、「ユーザーが入力した名前に応じてあいさつ文を変える」「入力された数値の合計を計算する」といった、入力に応じて結果が変わるシステムを開発できます。
標準入力と対になる概念が、「標準出力」です。標準出力は、プログラムから外部へデータを出す仕組みです。Javaでは、System.out.printlnを使います。
- 標準入力:外部 → プログラム(データを受け取る)
- 標準出力:プログラム → 外部(結果を表示する)
なお、プログラムの外部から値を渡す仕組みには、「コマンドライン引数」(mainメソッドの引数 args)もあります。コマンドライン引数は、プログラムの起動時に一度だけ値を渡す仕組みです。対して標準入力は、実行中に何行でも続けてデータを受け取れるという違いがあります。
Javaの標準入力をScannerクラスで受け取る(nextLine・next)
Javaで標準入力を受け取るもっとも基本的な方法は、java.util.Scanner クラスを使うことです。
Scannerクラスを使うには、まずファイルの先頭で import java.util.Scanner; と記述し、new Scanner(System.in) でScannerオブジェクトを作成します。
System.in が標準入力そのものを表し、Scannerは、標準入力から受け取ったデータを、文字列や数値として扱いやすい形に変換してくれるクラスです。
なお、import java.util.Scanner; を書き忘れると「シンボルを見つけられません(cannot find symbol)」というコンパイルエラーになります。Scannerを使ったプログラムでコンパイルエラーが出たときは、まずimport文があるかどうかを確認しましょう。
nextLineメソッド:1行まるごと文字列として受け取る
nextLine メソッドは、標準入力から1行分のデータを文字列(String型)として受け取ります。行末の改行文字は含まれません。
出力結果
こんにちは、paizaさんnextLine を複数回呼び出すと、呼び出すたびに次の行を読み込みます。空白(スペース)を含む行も、1行まるごと1つの文字列として受け取れるのが特徴です。
nextメソッド:空白区切りで1つずつ受け取る
next メソッドは、空白文字を区切りとして、値を1つずつ文字列として受け取ります。区切りになる空白文字には、改行だけでなく、タブや全角・半角スペースなども含まれます。
出力結果
apple
banana【paizaラーニングの関連講座】
新・Java入門編15:Scannerを使用した標準入力からの値の取得方法について学習しよう
Javaの標準入力で数値を受け取る方法(nextInt・nextDouble)
標準入力から受け取った値を計算に使う場合は、nextInt や nextDouble を使って数値として受け取ります。
前述のnextLine や next を使って受け取った値は、文字列(String型)となります。文字列のまま + 演算子を使うと、足し算ではなく文字列の連結になってしまうので注意しましょう。
出力結果
51上記のコードでは、「5 + 1」の計算結果である「6」ではなく、文字列「5」と数値「1」が連結された「51」が出力されてしまいます。
数値として計算したい場合は、nextInt メソッドを使いましょう。
出力結果
6nextInt は空白や改行を区切りとして、値を1つずつint型の整数として受け取ります。
小数を受け取りたい場合は nextDouble、long型の大きな整数を受け取りたい場合は nextLong と、受け取りたい型に応じたメソッドが用意されています。
出力結果
3.75なお、nextInt で受け取れるのは、int型の範囲(約±21億)までです。それを超える大きな整数が入力される可能性がある場合は、nextLong を使ってlong型で受け取りましょう。
また、nextLine で文字列として受け取ってから、Integer.parseInt で整数に変換する方法もあります。
出力結果
20上記のコードは、「nextInt と nextLine を混ぜたときの落とし穴」を避けられるため、行単位で入力を処理したいときに便利です。
【paizaラーニングの関連講座】
新・Java入門編15:nextIntを使った標準入力からの値取得
新・Java入門編6:変数を学習しよう
Javaの標準入力で複数の値・複数行のデータを受け取る方法
1行に複数の値がある場合や、入力が複数行にわたる場合は、Scannerのメソッドとfor文(繰り返し処理)を組み合わせて受け取ります。
受け取り方には、「next系のメソッドで1つずつ読む方法」と「nextLineで1行をまとめて読み、splitで分割する方法」の2つがあり、どちらでも同じ処理を実現できます。
値を読み込みながらすぐに計算するならnext系、1行分を文字列としてまとめて加工したいならsplitと、状況に応じて使い分けましょう。
1行に複数の値がある場合:nextを繰り返すかsplitを使う
「1 2 3」のように1行に空白区切りで複数の値がある場合、next や nextInt は空白を区切りとして1つずつ値を読み進めるため、そのまま複数回呼び出せば受け取れます。
出力結果
6また、nextLine で1行を文字列として受け取り、Stringクラスの split メソッドで分割する方法もよく使われます。
split(" ") と書くと半角スペース1つで区切りますが、1つ以上の連続する空白文字で区切る split("\\s+") を使うほうが、より安全で一般的です。
出力結果
6複数行の入力:先頭行で行数を受け取ってfor文で繰り返す
「1行目にデータの件数N、2行目以降にN行のデータ」という入力形式の場合は、まず先頭行の件数を受け取り、その回数だけfor文で読み込みを繰り返すとよいでしょう。
出力結果
60受け取った値をあとから使いたい場合は、配列やArrayListに格納しておきます。
要素数をあとから増やせるArrayListを使う場合は、次のように書きます。
list.add で受け取った値を末尾に追加し、拡張for文で全要素を順番に処理しています。ArrayListを使う場合は、ファイルの先頭に import java.util.ArrayList; の記述が必要です。
【paizaラーニングの関連講座】
新・Java入門編13:for文を学習しよう
新・Java入門編29:配列について学習しよう
新・Java入門編9:ArrayListを学習しよう
入力の個数がわからない場合:hasNextで最後まで読み込む
入力が何件あるか事前にわからない場合は、hasNext・hasNextLine・hasNextInt などのメソッドを使って、「次の入力がある間だけ読み込む」というwhile文を書きます。
出力結果
60hasNextInt は、次に読み取れる整数が残っていればtrue、なければfalseを返すメソッドです。入力の終わり(EOF)まで、すべてのデータを処理したいときの定番の書き方なので、あわせて覚えておきましょう。
【paizaラーニングの関連講座】
新・Java入門編17: while文を学習しよう
複数行・複数列のデータ:2次元配列で受け取る
行と列を持つ表形式のデータは、for文を入れ子(ネスト)にして2次元配列に格納します。以下は、1行目で行数Nと列数Mを受け取り、続くN行M列の整数を2次元配列に格納するコードです。
出力結果
※以下の内容の2次元配列が作成される
[[1, 2, 3], [4, 5, 6]]nextInt は空白も改行もまとめて区切りとして扱うため、「1行に複数列」「複数行」が混在した入力でも、同じ書き方で読み進められます。
なお、nextLine と split の組み合わせでも、同じデータを受け取れます。その場合は、「1行読む → splitで分割する → 各要素をparseIntで変換する」という処理を、for文で行数分繰り返します。
どちらの書き方でも問題ありませんが、nextInt を使ったほうがコードを短くできます。
【paizaラーニングの関連講座】
新・Java入門編16:複数のデータを標準入力から取得しよう
Javaで標準入力を扱う際によくあるエラーと対処法
Javaの標準入力でエラーが出たときは、「入力の形式」と「読み取るメソッド」が一致しているかを確認するのが解決の近道です。
ここからは、初心者がつまずきやすい4つのケースを紹介します。エラーメッセージは英語で表示されますが、Exception in thread "main" に続く例外名(エラーの種類)と、at Main.main(Main.java:5) のような行番号を読み取れば、「どの行で・何が」起きたのかを特定できます。
InputMismatchException:nextIntに数値以外の入力を渡している
nextInt で読み取ろうとした値が整数として解釈できない場合、InputMismatchExceptionが発生します。
出力結果
Exception in thread "main" java.util.InputMismatchException入力データが本当に数値なのか、読み取る順番がずれて文字列部分を nextInt で読もうとしていないかを確認しましょう。
NoSuchElementException:入力がもうないのに読み取ろうとしている
入力データをすべて読み終えたあとに next や nextLine を呼び出すと、NoSuchElementExceptionが発生します。「行が見つからない(No line found)」というメッセージが表示されることもあります。
問題文の入力形式をよく読み、入力の行数・個数と読み取り回数が一致しているかを確認しましょう。なお、典型的な原因は「for文の繰り返し回数が1回多い」ことです。
NumberFormatException:parseIntに数値以外の文字列を渡している
Integer.parseInt は、Scannerの nextInt() と違い、文字列の前後に空白が含まれているだけでもエラーになります。
split(" ") を使った際に連続する空白が空文字 "" として分割されたり、不要なスペースが残ったまま渡されたりするケースがよくあります。このエラーが起きたときは、変換前の文字列を System.out.println で出力し、前後に見えない空白や空文字が混入していないか確認しましょう。
nextIntのあとのnextLineが空文字になる
nextInt(や next)と nextLine を混ぜて使うと、想定外の動作をすることがあります。nextInt は数値の直後にある改行文字を読み残すため、直後に nextLine を呼び出すと、その読み残した改行までの「空の文字列」を受け取ってしまうのです。
対処法は2つあります。1つは nextInt のあとに空読み用の sc.nextLine(); を1回挟む方法、もう1つは入力をすべて nextLine で受け取り、数値が必要な行だけ Integer.parseInt で変換する方法です。
どのエラーでも、基本のデバッグ手順は同じです。まず例外名と行番号からエラーの発生箇所を特定し、その行で読み取ろうとしているデータと、実際の入力データの形式を見比べます。
それでも原因がわからないときは、受け取った直後の値をそのまま System.out.println で出力してみると、想定と違う値が入っていることがわかるでしょう。
【paizaラーニングの関連講座】
新・Java入門編27:例外について学習しよう
よくある質問(Q&A)
Javaの標準入力に関するよくある質問(FAQ)
Q.nextとnextLineは、どのように使い分ければよいですか?
A.空白区切りの値を1つずつ受け取りたいときは next(数値なら nextInt)、空白を含む1行をまるごと受け取りたいときは nextLine を使います。たとえば「山田 太郎」という氏名を1つの文字列として受け取りたい場合は nextLine が適しています。
なお、両者を混ぜて使うと改行の読み残しによる想定外の動作が起きやすいため、1つのプログラム内ではどちらかに寄せるのがおすすめです。
Q.カンマ区切りなど、空白以外の文字で区切られた入力はどう受け取ればいいですか?
A.nextLine で1行を文字列として受け取り、split(",") のように区切り文字を指定して分割すると簡単です。
Scannerの useDelimiter メソッドで区切り文字自体を変更する方法もありますが、まずは split を使う方法を覚えましょう。
Q.標準入力で受け取った文字列を1文字ずつ処理するには?
A.nextLine で1行を文字列として受け取り、charAt メソッドで1文字ずつ取り出すのが基本的な方法です。
文字列の長さは、 length メソッドで取得できます。また、split("") で1文字ずつの配列に分割する方法もあります。
Q.Scannerは、使い終わったらcloseする必要がありますか?
A.ファイルやネットワークを読み取るScannerは、リソース解放のために close を呼ぶべきです。ただ、標準入力(System.in)を読み取るScannerは、プログラムの終了時にOSによってリソースが自動的に回収されるため、スキルチェックなどではcloseしなくても実害はほとんどありません。
むしろ注意したいのは、sc.close() を呼ぶと、 System.in そのものが閉じられてしまう点です。閉じたあとで、別のScannerを作って標準入力を読み取ろうとすると、エラーになってしまいます。そのため、closeする場合はプログラムの最後で1回だけにしましょう。
Q.paizaのスキルチェック問題で、コードが合っているはずなのに「不正解」になってしまう原因は何ですか?
A.出力形式が、期待される答えと完全に一致していない可能性があります。よくある原因は以下の3つです。
- 「値を入力してください」などの案内文(プロンプト)まで出力してしまっている
- System.out.print と System.out.println の使い分けを誤り、改行の位置が期待と異なっている
- 数値の前後に余分な空白や文字列を出力している
スキルチェックでは、答えの値「だけ」を期待された形式で出力するのが原則です。
Q.大量の入力データを処理する際、実行時間を短くする(高速化する)方法はありますか?
A.入力の行数が数十万行を超えるような問題では、Scannerの代わりにBufferedReaderを使うと読み込みを高速化できます。
BufferedReaderは入力をまとめて読み込む(バッファリングする)ため、1件ずつ解析するScannerよりも高速ですが、Scannerの nextInt() のように空白区切りで1件ずつ読み進めることはできません。readLine() は必ず1行まるごとを文字列として読み取るため、1行に複数の数値が含まれる場合は、自分で split を使って分割し、Integer.parseInt で変換する必要があります。通常の学習や小規模な入力なら、Scannerで十分です。
まとめ
この記事では、Javaの標準入力の受け取り方について解説しました。ポイントを整理します。
- 標準入力とは、実行中のプログラムに外部からデータを渡す仕組みのこと
- Javaでは new Scanner(System.in) でScannerオブジェクトを作って受け取るのが基本
- 1行まるごとは nextLine、空白区切りは next、整数は nextInt と入力形式に応じて使い分ける
- 複数行・複数列のデータは、for文と配列(2次元配列)を組み合わせて受け取る
- nextInt と nextLine の混在による改行の読み残しなど、典型的な落とし穴に注意する
標準入力の扱い方は、実際に手を動かしてこそ身につきます。paizaラーニングの新・Java入門編では、ブラウザ上でコードを書きながら、標準入力を含むJavaの基礎を動画で学習できます。基本をひと通り学んだら、paizaのスキルチェックで腕試しをしてみましょう。標準入力を使った問題を解くことで、実践的なコーディング力が身につきます。
【paizaラーニングの関連講座】
新・Java入門編14:標準入力と標準出力を学習しよう
新・Java入門編
【paizaラーニングの練習問題】
標準入力サンプル問題セット
【プログラミング問題を解いて力試し】
プログラミングスキルを計れるpaizaのスキルチェック