標準入出力

コンソールへの出力

コンソールへの出力は, 標準出力と標準エラー出力の2系統があります。

class Test {
    public static void main(String args[]) {
        System.out.println("標準出力です");
        System.err.println("標準エラー出力です");
    }
}

これを通常通り java Test として実行すると

標準出力です
標準エラー出力です
と画面に出力されます。

しかし,java Test >xxx のようにリダイレクトすると,

標準エラー出力です
だけ画面に出力され,
標準出力です
のほうはファイル xxx に出力します。

つまり,

System.out.println()
通常はコンソールに出力するが, リダイレクトするとファイルに出力する
System.err.println()
いつもコンソールに出力する
ということになります。

なお,System.out.println("何々") は出力の後で改行しますが, System.out.print("何々") は改行しません。 特別な場合として,引数なしの System.out.println() は改行だけします。

入力(文字コード)

System.out.read() が, キーボードからの入力を読むための最も基本的な命令です。 これは,リターンキー(Enterキー)が押されるまでブロック (block,待つこと)します。 リターンキーが押されたら,最初に入力したキーの文字コード値を返します。

たとえば次のプログラムを考えましょう。

class Test {
    public static void main(String args[])
    throws java.io.IOException {    // 入出力エラーがありうる
        int c;                                // 変数 c を作る
        while ((c = System.in.read()) != -1)  // キー入力を c に
            System.out.println(c);            // c を出力
    }
}

ちょっとややこしい書き方がしてありますが, これは次のように書くのと同じことです。

class Test {
    public static void main(String args[])
    throws java.io.IOException {    // 入出力エラーがありうる
        int c;                      // int 型の変数 c を作る
        while (true) {              // 以下を繰り返す:
            c = System.in.read();   //   キー入力を c に代入
            if (c == -1) break;     //   c が -1 ならループ脱出
            System.out.println(c);  //   c を出力
        }
    }
}

throws java.io.IOException については少し後で説明します。

このプログラムを実行すると,入力待ちの状態になります。 キーボードからたとえば abc リターン と入力すると, 画面には

    97
    98
    99
    10
と出ます。これは, だからです。

System.in.read() は,「入力の終わり」を意味する特別な キー操作をすると,-1 という値を戻してきます。 UNIX の場合 Ctrl-D(コントロールキーを押した状態で d をたたく) で、この特別な値が返ってきます。 上のプログラムは,この値が戻ってきたらループを脱出するようにしてあります。

さて,main の最初に戻って,通常は

    public static void main(String args[]) {
で良かったのに,このプログラムでは
    public static void main(String args[])
                       throws java.io.IOException {
のように throws java.io.IOException を付けなければなりません。 これは,I/O(アイオー,Input/Output,入出力) でException(例外状態,要するにエラー)が起こるかもしれないことの宣言です。 データ入力を伴うプログラムでは,このような宣言が必要です。 もしこれを忘れたら,コンパイル時に次のようなエラーメッセージが出ます。
Exception java.io.IOException must be caught, or it must be declared in the throws clause of this method.

ちなみに,java.io.IOException のような長い名前を 書くのは面倒なので,通常はプログラムの最初に

    import java.io.*;
と書いておきます。そうすば,java.io の部分が省略できて,単に
    public static void main(String args[]) throws IOException {
と書くだけでよくなります。以下ではこの書き方をよく使います。

入力(文字列)

次のプログラムを実行すると「お名前は?」と尋ねてきますので, キーボードからたとえば 花子 と入れて リターンキーを押してください。 「こんにちは,花子さん」と答えてくれるはずです。

import java.io.*;
class Test {
    public static void main(String args[]) throws IOException {
        DataInputStream d = new DataInputStream(System.in);
                                        // データ入力の準備
        System.out.print("お名前は? "); // 画面出力
        System.out.flush();             // 強制出力
        String s = d.readLine();        // 文字列の入力
        System.out.println("こんにちは," + s + "さん");
    }
}

ここでも import java.io.*; が出てきましたね。 これを書かないと,

IOException は java.io.IOException
DataInputStream は java.io.DataInputStream
のように正式名を使わなければなりません。

キーボードから文字列を入力するには, System.in を補強するための次のような命令が必要です。

    DataInputStream d = new DataInputStream(System.in);
補強した System.in をここでは d と名づけています。

次の画面出力

    System.out.print("お名前は? ");
には,最後に改行する System.out.println(...) の代わりに, 改行しない System.out.print(...) を使いました。 ところが,Java言語の System.out では,効率化のため, 改行が来るまでデータを内部に溜めておき, 改行が来たらまとめて出力するしくみになっています。 そこで,行の途中で強制出力するために
    System.out.flush();           // 強制出力
が必要なのです。

文字列の入力は,さきほどの d を使って,

    String s = d.readLine();      // 文字列の入力
とします。

プログラムの実行が d.readLine() のところまで来ると, コンピュータは入力待ちの状態になります。 そこで例えば 花子 と打ち込み,リターンキーを押せば, s に「花子」という文字列が入ります。

入力(int 型)

次のプログラムを実行すると「あなたは何歳ですか?」と尋ねてきますので, 例えば40歳なら, キーボードから 40 と入れてリターンキーを押してください。 「きっと去年は 39 歳だったでしょう」と教えてくれるはずです。

import java.io.*;
class Test {
    public static void main(String args[]) throws IOException {
        DataInputStream d = new DataInputStream(System.in);
                                      // データ入力の準備
        System.out.print("あなたは何歳ですか? ");
        System.out.flush();           // 強制出力
        String s = d.readLine();      // 文字列の入力
        int a = Integer.parseInt(s);  // 整数に変換
        System.out.println("きっと去年は " + (a - 1) +
                           " 歳だったでしょう");
    }
}

整数の入力は,まず

        String s = d.readLine();      // 文字列の入力
で文字列を入力してから,
        int a = Integer.parseInt(s);  // 整数に変換
で整数に変換しています。

入力(long 型)

次のprogramは,金額を入力すると, 消費税(入力額の5%)と税込み価格を出力します。 int 型では20億円程度しか扱えませんので, long 型を使います。

import java.io.*;
class Test {
    public static void main(String args[]) throws IOException {
        DataInputStream d = new DataInputStream(System.in);
                                      // データ入力の準備
        System.out.print("金額? ");   // 画面出力
        System.out.flush();           // 強制出力
        String s = d.readLine();      // 文字列の入力
        long x = Long.parseLong(s);   // long型に変換
        long tax = 5 * x / 100;       // 消費税を求める(切捨て)
        long total = x + tax;         // 合計金額を求める
        System.out.println("金額: " + x +
                           "  消費税: " + tax +
                           "  合計: " + total);
    }
}

10行目では入力金額を5倍して100で割って消費税を求めています。 整数の割り算ですので, 小数点以下は切捨てになります。

これを四捨五入にするには,

        long tax = (5 * x + 50) / 100; // 消費税を求める(四捨五入)
とします。また,切上げにするには,
        long tax = (5 * x + 99) / 100; // 消費税を求める(切上げ)
とします。

入力(double 型)

次のprogramを実行すると,円の半径を聞いてきます。 半径を入力すると円の面積を出力します。

import java.io.*;
class Test {
    public static void main(String args[]) throws IOException {
        DataInputStream d = new DataInputStream(System.in);
                                      // データ入力の準備
        System.out.print("半径? ");   // 画面出力
        System.out.flush();           // 強制出力
        String s = d.readLine();      // 文字列の入力
        double r = Double.valueOf(s).doubleValue();
                                      // double型に変換
        double a = Math.PI * r * r;   // Math.PI は円周率
        System.out.println("半径 " + r + " の円の面積は "
                           + a + " です。");
    }
}

実行すると「半径?」と聞いてきます。 半径を例えば 5 のように打ち込むと,

    半径 5 の円の面積は 78.5398 です。
のように出力されます。