
Java超|入出力とストリームのしくみ
データは、川のように流れてプログラムへ入り、また外へ出ていく。ストリームの考え方をつかむと、画面表示・キーボード入力・ファイル入出力が、ひとつの大きな流れとして理解できるようになります。
Javaのプログラムでは、画面に文字を表示したり、キーボードから入力を受け取ったりする処理がよく出てきます。
たとえば、次のような処理です。
System.out.println("メッセージ");これは、画面に文字を表示する出力です。
一方、キーボードから文字を受け取る処理では、System.in や BufferedReader などが登場します。
最初は、画面表示、キーボード入力、ファイル操作は、それぞれ別々のしくみに見えるかもしれません。
しかし、Javaではこれらを ストリーム という共通の考え方で整理できます。
ストリームとは、簡単にいうと データの流れ です。
ドラゴンボール風にたとえると、戦士本部と各地の戦士たちをつなぐ通信ラインのようなものです。
悟空やベジータから本部へ修行報告が届く流れもあれば、本部から戦士たちへ任務指令が送られる流れもあります。
| Javaの考え方 | ドラゴンボール風のイメージ |
|---|---|
| 入力 | 外から戦士本部へ届く報告 |
| 出力 | 戦士本部から外へ出す指令 |
| ストリーム | 報告や指令が流れる通信ライン |
| System.in | キーボードから届く報告の入口 |
| System.out | 画面へ指令を出す出口 |
この記事では、入出力とは何か、ストリームとは何か、System.in と System.out は何をしているのか、そして Sample6.java のプログラムでキーボード入力がどのように文字列として読み取られるのかを整理していきます。
入出力とは何か
入出力とは、プログラムと外部とのやりとりです。
プログラムの中だけで計算して終わる処理もありますが、実際のプログラムでは外部とのやりとりがとても重要です。
たとえば、ユーザーが入力した文字を受け取る、計算結果を画面に表示する、データをファイルへ保存する、といった処理があります。
| 種類 | 内容 | 例 |
|---|---|---|
| 入力 | 外からデータを受け取ること | キーボードから文字を受け取る |
| 出力 | データを外へ出すこと | 画面にメッセージを表示する |
ドラゴンボール風に言えば、入力は戦士から本部へ届く報告です。
「修行が完了しました」
「重力設定を変更してください」
「次の任務地を教えてください」
このような情報が外から本部へ入ってくるイメージです。
一方、出力は本部から戦士へ出す指令です。
「修行メッセージを入力してください」
「修行記録を確認しました」
「次の任務へ向かってください」
このように、プログラムの内側から外へ情報を出すのが出力です。
ストリームとは何か
ストリームは、データの流れを表す考え方です。
Javaでは、キーボード、画面、ファイルなど、相手が違っても、データが流れる通り道として入出力を考えます。
つまり、ストリームは、装置そのものではなく、データが流れる道に注目する考え方です。
| 相手 | データの流れ |
|---|---|
| キーボード | 外からプログラムへ文字が入る |
| 画面 | プログラムから外へ文字が出る |
| ファイル | ファイルから読む、またはファイルへ書く |
ドラゴンボール風にたとえると、ストリームは戦士本部の通信ラインです。
報告が本部へ向かう道もあれば、本部から戦士へ指令が向かう道もあります。
相手が悟空でも、ベジータでも、ブルマの端末でも、ファイル保管庫でも、情報が流れるという考え方は共通です。
Javaでも同じです。
画面、キーボード、ファイルは別々のものですが、データが入る・出るという流れで見ると、共通した考え方で扱えるようになります。
なぜストリームで考えるのか
もし、キーボード用、画面用、ファイル用で、完全に別々の考え方を覚える必要があったら、入出力の学習はかなり大変になります。
しかし、ストリームという考え方があると、次のように整理できます。
| やりたいこと | ストリームでの見方 |
|---|---|
| キーボードから読む | 入力の流れを読む |
| 画面に表示する | 出力の流れへ書く |
| ファイルから読む | ファイルからの入力の流れを読む |
| ファイルへ保存する | ファイルへの出力の流れへ書く |
つまり、相手が変わっても、基本は「読む」「書く」という流れで考えられます。
ドラゴンボール風に言えば、通信の相手が戦士本部でも修行場でも任務地でも、情報が流れるという考え方は変わりません。
通信ラインを理解すれば、どこから情報が来て、どこへ情報を送るのかが見えやすくなります。
図:入出力とストリームの全体像

この図が示していること
この図では、Javaプログラムを中心に、キーボード、画面、ファイルとの間でデータが流れる様子を表しています。
キーボードからプログラムへ向かう流れは入力です。
画面へ向かう流れは出力です。
ファイルとは、読み込みと書き込みの両方ができます。
| 図の要素 | 意味 |
|---|---|
| System.in | キーボードからの入力の入口 |
| System.out | 画面への出力の出口 |
| 入力ストリーム | 外からプログラムへ入るデータの流れ |
| 出力ストリーム | プログラムから外へ出るデータの流れ |
| ファイル | 読むことも書くこともできる入出力先 |
この図から分かることは、入出力は相手が違っても、データの流れとして共通して考えられるということです。
画面とキーボードでもストリームが使われている
ストリームというと、ファイルの読み書きだけを思い浮かべるかもしれません。
しかし、すでに使ってきた画面表示やキーボード入力にも、ストリームの考え方が関係しています。
画面への出力では、よく次のように書きます。
System.out.println("修行開始");ここで使っている System.out は、標準出力を表します。
標準出力とは、プログラムから外へデータを出す基本の出口です。
多くの場合、画面に表示されます。
一方、キーボードからの入力では System.in が使われます。
System.inSystem.in は、標準入力を表します。
標準入力とは、外からプログラムへデータが入ってくる基本の入口です。
多くの場合、キーボードからの入力です。
| 名前 | 意味 | 主な相手 |
|---|---|---|
| System.in | 標準入力 | キーボード |
| System.out | 標準出力 | 画面 |
ドラゴンボール風にたとえると、System.in は戦士から本部へ届く報告窓口です。
System.out は、本部から戦士や画面へ指令を出す連絡窓口です。
標準入力と標準出力
標準入力と標準出力は、Javaプログラムが外部とやりとりするための基本的な入口と出口です。
| 項目 | 役割 | ドラゴンボール風のイメージ |
|---|---|---|
| 標準入力 | 外からデータを受け取る | 戦士から本部へ届く報告 |
| 標準出力 | 外へデータを出す | 本部から出す指令や連絡 |
| System.in | 標準入力を表す | 報告を受け取る窓口 |
| System.out | 標準出力を表す | 指令を出す窓口 |
これまで何気なく使ってきた System.out.println も、実はストリームを使った出力の一種です。
System.out.println("修行メッセージを入力してください。");この1行は、プログラムの中にある文字列を、System.out という出力の流れに乗せて画面へ送っています。
一方、System.in は、キーボードから入ってくるデータの流れです。
ただし、System.in だけでは、文字列を1行ずつ扱うには少し不便です。
そこで、InputStreamReader や BufferedReader というクラスを組み合わせて、読み取りやすい形に整えていきます。
キーボードからの入力と出力までの流れを見る
ここでは、キーボードから修行メッセージを入力し、それを画面に表示するプログラムを見ていきます。
ファイル名:Sample6.java
import java.io.*;
class Sample6
{
public static void main(String[] args)
{
System.out.println("修行メッセージを入力してください。");
try
{
InputStreamReader isr =
new InputStreamReader(System.in);
BufferedReader br =
new BufferedReader(isr);
String str = br.readLine();
System.out.println("入力された修行メッセージは「" + str + "」です。");
}
catch(IOException e)
{
System.out.println("入出力で問題が発生しました。");
}
}
}このプログラムでは、最初に画面へ入力を促すメッセージを表示します。
System.out.println("修行メッセージを入力してください。");そのあと、try ブロックの中でキーボード入力を読み取る準備をしています。
InputStreamReader isr =
new InputStreamReader(System.in);
BufferedReader br =
new BufferedReader(isr);
String str = br.readLine();そして、読み取った文字列を画面へ表示します。
System.out.println("入力された修行メッセージは「" + str + "」です。");プログラムの流れ
Sample6.java の処理は、次の順番で進みます。
| 手順 | 内容 |
|---|---|
| 1 | 画面に入力を促すメッセージを表示する |
| 2 | System.in をもとに InputStreamReader を作る |
| 3 | InputStreamReader をもとに BufferedReader を作る |
| 4 | readLine で1行読み込む |
| 5 | 読み込んだ文字列を画面に表示する |
| 6 | 入出力で問題が起きたら IOException を catch する |
この流れを見ると、キーボードから入力された文字が、いきなり String として読めているわけではないことが分かります。
System.in から入ってきたデータを、InputStreamReader で文字として扱いやすくし、BufferedReader で1行ずつ読みやすくしているのです。
ドラゴンボール風にたとえると、戦士から届いた通信データを、まず読める文字に変換し、さらにブルマの記録システムが1通の報告として整理しているようなイメージです。
InputStreamReader の役割
InputStreamReader は、入力ストリームを文字として扱いやすくするためのクラスです。
Sample6.java では、次のように使っています。
InputStreamReader isr =
new InputStreamReader(System.in);System.in は、キーボードから入ってくる標準入力です。
ただし、System.in はそのままだと、文字列を1行ずつ読むためには扱いにくい形です。
そこで、InputStreamReader を使い、入力の流れを文字として扱いやすくします。
| クラス | 役割 |
|---|---|
| System.in | キーボードから入ってくる標準入力 |
| InputStreamReader | 入力ストリームを文字として扱いやすくする |
ドラゴンボール風にたとえると、System.in は戦士から届く生の通信データです。
しかし、そのままでは記録係が読みやすい報告書にはなっていません。
InputStreamReader は、その生の通信データを、文字として読める形に変換する通訳係のような役割を持っています。
BufferedReader の役割
次に登場するのが BufferedReader です。
BufferedReader br =
new BufferedReader(isr);BufferedReader は、文字を効率よく読み込むためのクラスです。
さらに、readLine メソッドを使って、1行単位で文字列を読み取れるようにしてくれます。
| クラス・メソッド | 役割 |
|---|---|
| BufferedReader | バッファを使って効率よく文字を読み込み、1行ずつ扱いやすくする |
| readLine | 1行分の文字列を読み取る |
バッファとは、データをいったんためておく場所のようなものです。
細かい文字をその場その場で少しずつ処理するのではなく、ある程度まとめて扱えるようにするため、効率よく読み取れます。
ドラゴンボール風にたとえると、通信の断片をその場で一つずつ読むのではなく、ブルマの記録装置がいったんまとめてから、1つの報告として読み上げるようなものです。
readLine で1行読み込む
実際にキーボードから1行読み込んでいるのは、次の行です。
String str = br.readLine();readLine は、1行分の文字列を読み取るメソッドです。
ユーザーがキーボードで文字を入力し、Enter を押すと、その1行が文字列として読み取られます。
たとえば、ユーザーが次のように入力したとします。
重力修行を開始します
すると、その1行全体が str に入ります。
| 入力 | str に入る内容 |
|---|---|
| 重力修行を開始します | 重力修行を開始します |
| かめはめ波の型を確認します | かめはめ波の型を確認します |
| 任務報告を送ります | 任務報告を送ります |
そのあと、次の文で画面へ表示します。
System.out.println("入力された修行メッセージは「" + str + "」です。");つまり、キーボードから入った文字列を、プログラムの中で str という変数に入れ、System.out によって画面へ出力しているわけです。
図:キーボード入力が文字列になるまで

この図が示していること
この図では、キーボードから入力されたデータが、どのように文字列として取り出されるのかを表しています。
キーボードから入ったデータは、まず System.in という標準入力の入口を通ります。
その後、InputStreamReader によって文字として扱いやすくされます。
さらに BufferedReader によって効率よく読み込めるようになり、readLine によって1行分の文字列として取得されます。
| 流れ | 役割 |
|---|---|
| キーボード | ユーザーが文字を入力する |
| System.in | 標準入力の入口 |
| InputStreamReader | 入力を文字として扱いやすくする |
| BufferedReader | 効率よく読み込み、1行ずつ扱えるようにする |
| readLine | 1行分の文字列を取得する |
| System.out.println | 取得した文字列を画面へ表示する |
この図から分かることは、キーボード入力は複数のクラスを組み合わせて、読みやすい形に整えられているということです。
実行結果のイメージ
Sample6.java を実行すると、まず入力を促すメッセージが表示されます。
修行メッセージを入力してください。ここで、たとえば次のように入力します。
重力修行を開始しますすると、次のように表示されます。
修行メッセージを入力してください。
重力修行を開始します
入力された修行メッセージは「重力修行を開始します」です。この流れでは、入力と出力の両方が使われています。
| 表示・入力 | 種類 | 使っているもの |
|---|---|---|
| 修行メッセージを入力してください。 | 出力 | System.out |
| 重力修行を開始します | 入力 | System.in |
| 入力された修行メッセージは... | 出力 | System.out |
ここで重要なのは、キーボードから入ったデータがプログラム内の str に入り、その str の内容を画面へ出力していることです。
つまり、データは次のように流れています。
キーボード → System.in → InputStreamReader → BufferedReader → readLine → String str → System.out → 画面

ドラゴンボール風にたとえると、戦士が出した修行報告が、本部の入口、通訳係、記録係を通って巻物に記録され、最後に画面へ掲示されるような流れです。
なぜ import java.io.*; が必要なのか
Sample6.java の先頭には、次の1行があります。
import java.io.*;java.io は、入出力に関するクラスがまとめられているパッケージです。
今回のプログラムでは、InputStreamReader、BufferedReader、IOException を使っています。
これらは java.io パッケージに含まれるクラスです。
| クラス | 役割 |
|---|---|
| InputStreamReader | 入力を文字として扱いやすくする |
| BufferedReader | 効率よく文字を読み込む |
| IOException | 入出力で問題が起きたときの例外 |
import java.io.*; と書くことで、java.io パッケージ内のクラスを使いやすくしています。
もし import を書かない場合、クラス名を使うときに java.io.BufferedReader のように、パッケージ名まで含めて書く必要があります。
| 書き方 | 特徴 |
|---|---|
| import java.io.*; を書く | BufferedReader のように短く書ける |
| import を書かない | java.io.BufferedReader のように長く書く必要がある |
ドラゴンボール風に言えば、java.io は入出力に関する巻物棚です。
最初に import java.io.*; と書くことで、入出力の巻物棚を使う準備をしているイメージです。
なぜ IOException に備えるのか
Sample6.java では、try-catch が使われています。
try
{
InputStreamReader isr =
new InputStreamReader(System.in);
BufferedReader br =
new BufferedReader(isr);
String str = br.readLine();
System.out.println("入力された修行メッセージは「" + str + "」です。");
}
catch(IOException e)
{
System.out.println("入出力で問題が発生しました。");
}ここで catch しているのは IOException です。
IOException は、入出力処理で問題が起きたときに使われる例外です。
キーボード入力やストリームの読み込みは、プログラムの内部だけで完結する計算とは違います。
外部とのやりとりが関係します。
外部とのやりとりでは、想定外の問題が起きる可能性があります。
| 処理 | 問題が起きる可能性 |
|---|---|
| キーボード入力 | 入力の読み込みに失敗する可能性 |
| ファイル読み込み | ファイルが存在しない、読み取れない可能性 |
| 通信 | 相手と接続できない可能性 |
| ストリーム処理 | データの流れが途中で問題を起こす可能性 |
そのため、入出力処理では IOException に備えることがあります。
ドラゴンボール風にたとえると、外部との通信には不確実さがあります。
通信データが途中で途切れるかもしれません。
通信装置が一時的に反応しないかもしれません。
報告が途中で壊れて届くかもしれません。
そのような入出力の問題に備えるために、IOException を catch しています。
try-catch の役割
このプログラムの try ブロックには、入出力に関係する処理が入っています。
String str = br.readLine();readLine は、1行分の文字列を読み取るメソッドです。
このような入出力処理では、IOException が起きる可能性があります。
そのため、try の中に入れて、問題が起きた場合は catch で受け止めます。
| ブロック | 役割 |
|---|---|
| try | 入出力処理を実行する |
| catch(IOException e) | 入出力の問題を受け止める |
try-catch を使うことで、問題が起きたときに、Javaの難しい例外メッセージだけで終わらせず、利用者に分かりやすいメッセージを表示できます。
System.out.println("入出力で問題が発生しました。");ドラゴンボール風に言えば、通信がうまく届かなかったときに、ブルマの支援システムが状況を受け止めて、
「入出力で問題が発生しました。」
と本部に知らせるようなものです。
図:入出力処理とIOExceptionの関係

この図が示していること
この図では、入出力処理と IOException の関係を表しています。
try ブロックでは、InputStreamReader、BufferedReader、readLine を使って入力を読み取っています。
しかし、入出力は外部とのやりとりなので、問題が起きる可能性があります。
その問題に備えるために、catch(IOException e) を用意しています。
| 図の要素 | 意味 |
|---|---|
| try ブロック | 入出力処理を実行する場所 |
| br.readLine() | 1行分の文字列を読み取る処理 |
| IOException | 入出力で問題が起きたときの例外 |
| catch(IOException e) | 入出力の問題を受け止める場所 |
この図から分かることは、入出力処理では外部とのやりとりがあるため、IOException に備える必要があるということです。
画面・キーボード・ファイルを同じ考え方で見る
この学習で大切なのは、Sample6.java のコードを覚えることだけではありません。
もっと大切なのは、入出力をストリームという共通の流れとして見ることです。
この考え方が身につくと、今後ファイル入出力を学ぶときにも理解しやすくなります。
| 今回の相手 | 今後出てくる相手 | 共通点 |
|---|---|---|
| キーボード | ファイル | データを読む |
| 画面 | ファイル | データを書く |
| System.in | ファイル入力用ストリーム | 入力の流れ |
| System.out | ファイル出力用ストリーム | 出力の流れ |
キーボード入力では、System.in からデータを受け取りました。
ファイル入力でも、考え方としてはファイルからデータを受け取ります。
画面出力では、System.out へデータを流しました。
ファイル出力でも、考え方としてはファイルへデータを流します。
ドラゴンボール風に言えば、通信の相手がキーボードなのか、画面なのか、ファイルなのかが違うだけです。
情報が流れるという基本は変わりません。
ストリームを理解すると入出力がつながって見える
ストリームの理解が深まると、Javaの入出力はばらばらの知識ではなく、ひとつながりの考え方として見えてきます。
| 用語 | 内容 |
|---|---|
| ストリーム | データの流れ |
| 入力ストリーム | 外からプログラムへ入る流れ |
| 出力ストリーム | プログラムから外へ出る流れ |
| System.in | 標準入力 |
| System.out | 標準出力 |
| InputStreamReader | 入力を文字として扱いやすくする |
| BufferedReader | 効率よく読み込み、1行ずつ扱いやすくする |
| readLine | 1行の文字列を読み込む |
| IOException | 入出力で起こる問題に備える例外 |
最初は InputStreamReader や BufferedReader の名前が長く感じるかもしれません。
しかし、役割で分けて考えると分かりやすくなります。
| クラス・メソッド | ドラゴンボール風の役割 |
|---|---|
| System.in | 報告が入ってくる本部の入口 |
| InputStreamReader | 生の通信を文字として読める形にする通訳係 |
| BufferedReader | 通信をためて1行ずつ読みやすくする記録係 |
| readLine | 1通の報告として読み取る |
| System.out | 画面へ指令を出す出口 |
この流れが分かると、Sample6.java のコードもかなり読みやすくなります。
キーボードから入った文字が、System.in から入り、InputStreamReader と BufferedReader を通って、readLine で String として取り出される。
そして、その String を System.out.println で画面へ表示する。
この一連の流れこそが、ストリームによる入出力の基本です。
