第22週目演習

下準備

テストドライバの導入

第22回目 (秋学期09回目) 分のテストドライバを導入する。以下の手順で行う。

  1. ダウンロード のページを開く (ここをクリック)
  2. プロジェクト「java2007」にある「test」の左側の「+」をクリック
  3. ツリーが展開されるので「install-libraries.xml」を右クリック
  4. 「実行(R)」にマウスカーソルを合わせる
  5. 「1 Ant ビルド」をクリック
  6. 「コンソール」タブに"BUILD SUCCESSFUL"と表示されれば成功
  7. eclipseの画面でプロジェクト「java2007」を右クリック
  8. メニューが表示されるので、「更新」をクリック
  9. "week22.zip" をデスクトップなどにダウンロード
  10. eclipseの画面でプロジェクト「java2007」を右クリック
  11. メニューから「インポート(I)」を選択
  12. 「インポート」ウィンドウが表示されるので、「Zip ファイル」を選択
  13. 「次へ(N)」をクリック
  14. 宛先フォルダー(L): が「java2007」になっていることを確認
  15. From zip file: の右側にある 「参照(R)...」をクリック
  16. ファイルダイアログが表示されるので、ダイアログ内に表示されたダウンロードしたファイルをダブルクリック
  17. 前の画面に戻るので、From zip file: のエリアに正しいパスが入力されていることを確認
  18. フォルダ「/」の左にチェックがついていることを確認 (ついていなければチェックボックスをクリック)
  19. 「警告を出さずに既存リソースを上書き」にチェックがついていることを確認 (上書きしたくないファイルがある場合はチェックを外す)
  20. 「終了 (F)」をクリック

第22週目テストドライバの導入に成功すると、java2007 プロジェクトの test フォルダに j2.lesson09.xml というファイルが作成される。

パッケージの作成

過去の演習を参考にして、「j2.lesson09」というパッケージを作成する。

様々な形式のデータをファイルに保存するプログラム

様々な形式のデータをファイルに保存するプログラム SimpleSerializer クラスを作成する。

このプログラムは、名前と得点をコンソールから入力し、その後に保存先ファイルの名前を入力すると、指定したファイルに入力した名前と得点をバイナリデータとして書き込む

名前を入力:ほげほげ
得点を入力:920
保存するファイル名を入力:pr2201.dat
ファイルpr2201.datに保存しました

上記のように実行した後、U:\pr2201.dat の内容を見てみると次のようになっている。


擬似コードの作成

「プログラム全体」の擬似コード

プログラム全体の擬似コードは以下のようにする。

プログラム全体
    print "名前を入力:"
    name = コンソール入力 (String)
    print "得点を入力:"
    score = コンソール入力 (int)
    if score が数値でない
        print "得点は数値で入力してください", 改行
        return
    print "保存するファイル名を入力:"
    savefile = コンソール入力 (String)
    savefile に name, score を保存
    if ファイル保存中にエラーが発生しなかった
        print "ファイル" + savefile + "に保存しました", 改行
    else (ファイル保存中にエラーが発生)
        print "ファイル" + savefile + "に保存できませんでした", 改行

上記のうち、「savefile に name, score を保存」という部分が抽象的である。これをメソッドに分解するため、詳細な擬似コードを書く。

「ファイルに保存」の擬似コード

ファイルに保存(savefile, name, score)
    out = savefile のファイルを書き込み用に開く
        outにwrite(name)
        outにwrite(score)

骨格の作成

クラスの作成

以下の手順で、パッケージ「j2.lesson09」に「SimpleSerializer」クラスを作成する。

  1. 先ほど作成したパッケージ 「j2.lesson09」の上で右クリック
  2. マウスカーソルを「新規」に合わせる
  3. 「クラス」をクリック
  4. クラス名は SimpleSerializer とする。

擬似コードの貼り付け (骨格のみ)

作成したクラスに、各擬似コードの名前を貼り付ける。ただし、このプログラムではファイルの出力やコンソール入力を行っているため、import java.io.*; もつける。

package j2.lesson09;

import java.io.*;

public class SimpleSerializer {
    // プログラム全体
    // ファイルに保存(savefile, name, score)
}

パッケージについてしっかり理解できていれば、次のクラスを必要に応じて個別にインポートしてもよい。

mainメソッドの作成 (骨格のみ)

擬似コード「プログラム全体」に合わせて、クラス「SimpleSerializer」内にpublic static void main(String[] args) から始まるメソッドを作成する。ただし、擬似コード「プログラム全体」で使う API は IOException を発生させる可能性があるため、throws で指定しておく。

save(String, String, int) メソッドの作成 (骨格のみ)

擬似コード「ファイルに保存」に合わせて、クラス「SimpleSerializer」内に private static void save(String savefile, String name, int score) から始まるメソッドを作成する。

ただし、このメソッドを呼び出す「プログラム全体」には、次のような擬似コードがある。

savefile に name, score を保存
if ファイル保存中にエラーが発生しなかった
    ...
else (ファイル保存中にエラーが発生)
    ...

save(String, String, int) メソッドで発生した例外を「プログラム全体」で捕捉しようとしている。呼び出し元に例外処理を任せているため、このメソッドには throws の指定が必要である

ファイルの入出力に関する例外は、IOException であるため、このメソッドでは throws IOException を指定する。

全体の骨格

ここまでのプログラムの骨格は以下のようになる。

package j2.lesson09;

import java.io.*;

public class SimpleSerializer {
    // プログラム全体
    public static void main(String[] args) throws IOException {
    }
    // ファイルに保存(savefile, name, score)
    private static void save(String savefile, String name, int score) throws IOException {
    }
}

骨格テスト

ここまでの作業をCtrl+Sを押して保存し、コンパイルを行う (保存時に自動で行われる)。ここでエラーが発生していたら文法エラーなので見直す。

「SimpleSerializerに対する骨格テスト」を実行する。

骨格テストを行った際に緑のバーが表示されれば、外側から見たプログラムの骨格は正しくなっている。

赤いバーが表示された場合、メッセージを元にプログラムを見直すこと。修正を行い、Ctrl+Sで保存した後に「Run」ボタンをクリックする。

メッセージ 詳細
(クラス名), existence j2.lesson09 に対象のクラスが存在していない。パッケージやクラス名を確認
(メソッド名), existence 指定されたメソッドが存在しない
(メソッド名), public メソッドを作る際に public が抜けている
(メソッド名), public メソッドを作る際に private が抜けている
(メソッド名), static メソッドを作る際に static が抜けている
(メソッド名), type <T> メソッドを作る際に戻り値の型を間違えている (正しくは <T>)
(メソッド名), throws java.io.IOException メソッドを作る際に throws IOException が抜けている

プログラムへの変換

main メソッド

先ほど作成した SimpleSerializer クラスの main メソッドの中身を記述する。

まずは擬似コードをコメントとして貼り付ける。

// プログラム全体
public static void main(String[] args) throws IOException {
    // print "名前を入力:"
    // name = コンソール入力 (String)
    // print "得点を入力:"
    // score = コンソール入力 (int)
    // if score が数値でない
        // print "得点は数値で入力してください", 改行
        // return
    // print "保存するファイル名を入力:"
    // savefile = コンソール入力 (String)
    // savefile に name, score を保存
    // if ファイル保存中にエラーが発生しなかった
        // print "ファイル" + savefile + "に保存しました", 改行
    // else (ファイル保存中にエラーが発生)
        // print "ファイル" + savefile + "に保存できませんでした", 改行
}

コンソール入力

擬似コードの下記の部分は、今までどおり入力を要求する文章を表示し、コンソール入力を行うだけなので問題ない。

print "名前を入力:"
name = コンソール入力 (String)
print "得点を入力:"
score = コンソール入力 (int)

これまでの知識で擬似コードを簡単に変換できる。

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
// print "名前を入力:"
System.out.print("名前を入力:");
// name = コンソール入力 (String)
String name = reader.readLine();
// print "得点を入力:"
System.out.print("得点を入力:");
// score = コンソール入力 (int)
int score = Integer.parseInt(reader.readLine());

入力のチェック

擬似コードの次の部分では、入力された内容のチェックを行っている。

if score が数値でない
    print "得点は数値で入力してください", 改行
    return

その直前では、次のようなプログラムを書いていた。

// score = コンソール入力 (int)
int score = Integer.parseInt(reader.readLine());

上記のように書くと、score が数値でない場合に NumberFormatException をスローしてプログラムが終了してしまう。そこで、数値に変換する部分から try-catch の形に書き直す必要がある。

次のようなパターンはよく見かけることがある。

<例外が発生するかもしれない処理>
if <例外が発生した>
    <例外処理>

例外という機構が存在しないプログラミング言語ならば上記と非常に似た形でプログラムを書けるが、Java には例外が存在するため、次のように書く必要がある。

try {
    <例外が発生するかもしれない処理>
}
catch((例外のタイプ) e) {
    <例外処理>
}

そのため、次のようなプログラムになる。

// score = コンソール入力 (int)
int score;
try {
    score = Integer.parseInt(reader.readLine());
}
// if score が数値でない
catch (NumberFormatException e) {
    // print "得点は数値で入力してください", 改行
    System.out.print("得点は数値で入力してください");
    // return
    return;
}

ファイルに保存する

擬似コードの次の部分では、ファイルに入力されたデータを保存している。

print "保存するファイル名を入力:"
savefile = コンソール入力 (String)
savefile に name, score を保存

「ファイルを保存する」というのは、別のメソッド save(String, String, int) を用意しているので、単純に書ける。

// print "保存するファイル名を入力:"
System.out.print("保存するファイル名を入力:");
// savefile = コンソール入力 (String)
String savefile = reader.readLine();
// savefile に name, score を保存
save(savefile, name, score);

入出力例外のチェック

擬似コードの次の部分では、ファイル保存時の例外処理を記述している。

if ファイル保存中にエラーが発生しなかった
    print "ファイル" + savefile + "に保存しました", 改行
else (ファイル保存中にエラーが発生)
    print "ファイル" + savefile + "に保存できませんでした", 改行

これも先ほどと同じように、例外に対して処理を行っているため、if の形式で書くことができない。先ほどの NumberFormatException の場合には if <例外が発生> しかなかったが、今度は else も考慮するため、少しパターンを変える。

<例外が発生するかもしれない処理>
if <例外が発生した>
    <例外処理>
else
    <正常処理>

上記のようなプログラムは、Java で次のように表現することができる。

try {
    <例外が発生するかもしれない処理>
    <正常処理>
}
catch((例外のタイプ) e) {
    <例外処理>
}

<正常処理> の直前の処理で例外が発生した場合、try 節を強制的に抜けてしまうために上記のように書くことができる。

擬似コードでは上記の if と else の条件が逆になっているので、注意しながら Java のプログラムに変換する。

// savefile に name, score を保存
try {
    save(savefile, name, score);
    // if ファイル保存中にエラーが発生しなかった
    // print "ファイル" + savefile + "に保存しました", 改行
    System.out.println("ファイル" + savefile + "に保存しました");
}
// else (ファイル保存中にエラーが発生)
catch (IOException e) {
    // print "ファイル" + savefile + "に保存できませんでした", 改行
    System.out.println("ファイル" + savefile + "に保存できませんでした");
}

save メソッド

次に、save メソッドの中身を記述する。

まずは擬似コードをコメントとして貼り付ける。

// ファイルに保存(savefile, name, score)
private static void save(String savefile, String name, int score) throws IOException {
    // out = savefile のファイルを書き込み用に開く
    // outにwrite(name)
    // outにwrite(score)
}

ファイルを開く処理

擬似コードの最初の部分では、ファイルを書き込み用に開いている。

out = savefile のファイルを書き込み用に開く

ファイルを書き込み用に開くには、FileOutputStream を使用する。コンストラクタに書き込み先のファイル名を指定すればいいので、次のようになる。

FileOutputStream out = new FileOutputStream(savefile);

しかし、ファイルを操作する場合には、バッファつきのストリームを作成しないと速度の面で不利である。そのため、次のように BufferedOutputStream を接続する。

BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(savefile));

さらに、今回書き込むデータは int 型のデータと String 型のデータである。このようなデータを書き込む場合、DataOutputStream を使うと便利であるという説明をした。

// DataOutputStream -> BufferedOutputStream -> FileOutputStream
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(savefile)));

ファイルを開いた場合、閉じる処理も同時に書く癖をつけるとよい。ファイルを開いて閉じる処理は次のように書ける。

<ファイルを開く処理>
try {
}
finally {
    <ファイルを閉じる処理>
}

最終的に、次のようなプログラムになる。

// out = savefile のファイルを書き込み用に開く
// DataOutputStream -> BufferedOutputStream -> FileOutputStream
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(savefile)));
try {
}
finally {
    out.close();
}

try 節にファイルを書き込む処理を記述していく。

ファイルに書き込む処理

擬似コードの次の部分では、ファイルに接続されたストリームに対して、実際にデータを書き出している。

outにwrite(name)
outにwrite(score)

score は String 型で、name は int 型である。そのため、単純に write メソッドを呼び出すのではなく、DataOutputStream で用意されている 様々なデータ型の値を書き込むためのメソッド を使用する。

クラス int 型を扱う double 型を扱う String 型を扱う
java.io.DataOutputStream writeInt(int) writeDouble(double) writeUTF(String)

上記を用いると、次のようなプログラムが書ける。

// outにwrite(name)
// # String name なので writeUTF
out.writeUTF(name);
// outにwrite(score)
// # int score なので writeInt
out.writeInt(score);

プログラムの実行

プログラムを実行する。

入力に "ほげほげ", "920", "U:/pr2201.dat" と与えると、コンソールには次のように表示される。

名前を入力:ほげほげ
得点を入力:920
保存するファイル名を入力:pr2201.dat
ファイルpr2201.datに保存しました

そして、Uドライブに pr2201.dat が作成されて、そのファイルの内容は次のようになっている。


機能テスト

ここまでの作業をCtrl+Sを押して保存し、コンパイルを行う (保存時に自動で行われる)。ここでエラーが発生していたら文法エラーなので見直す。

「SimpleSerializerに対する機能テスト」を実行する。

赤いバーが表示された場合、メッセージを元にプログラムを見直すこと。修正を行い、Ctrl+Sで保存した後に「Run」ボタンをクリックする。

メッセージ 詳細
期待された結果と異なります 出力された結果が期待された値と異なる。

機能テストの項目

項目名 テストの内容
sample .temp/pr01.dat に、サンプルと同じ内容を出力 (終了後に削除している)

プログラム全体

SimpleSerializerクラス全体を掲載しておく。

package j2.lesson09;

import java.io.*;

public class SimpleSerializer {
    // プログラム全体
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        // print "名前を入力:"
        System.out.print("名前を入力:");
        // name = コンソール入力 (String)
        String name = reader.readLine();
        // print "得点を入力:"
        System.out.print("得点を入力:");
        // score = コンソール入力 (int)
        int score;
        try {
            score = Integer.parseInt(reader.readLine());
        }
        // if score が数値でない
        catch (NumberFormatException e) {
            // print "得点は数値で入力してください", 改行
            System.out.print("得点は数値で入力してください");
            // return
            return;
        }
        // print "保存するファイル名を入力:"
        System.out.print("保存するファイル名を入力:");
        // savefile = コンソール入力 (String)
        String savefile = reader.readLine();
        // savefile に name, score を保存
        try {
            save(savefile, name, score);
            // if ファイル保存中にエラーが発生しなかった
            // print "ファイル" + savefile + "に保存しました", 改行
            System.out.println("ファイル" + savefile + "に保存しました");
        }
        // else (ファイル保存中にエラーが発生)
        catch (IOException e) {
            // print "ファイル" + savefile + "に保存できませんでした", 改行
            System.out.println("ファイル" + savefile + "に保存できませんでした");
        }
    }

    // ファイルに保存(savefile, name, score)
    private static void save(String savefile, String name, int score) throws IOException {
        // out = savefile のファイルを書き込み用に開く
        // DataOutputStream -> BufferedOutputStream -> FileOutputStream
        DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(savefile)));
        try {
            // outにwrite(name)
            // # String name なので writeUTF
            out.writeUTF(name);
            // outにwrite(score)
            // # int score なので writeInt
            out.writeInt(score);
        }
        finally {
            out.close();
        }
    }
}

様々な形式のデータを読み込むプログラム

ファイル内に格納された様々な形式のデータを読み込み、コンソールに表示するプログラムとして、SimpleDeserializer クラスを作成する。ただし、読み込むファイルの形式は、SimpleSerializer で作成できるファイルと同様の形式であるとする。

このプログラムは、読み込み元のファイルを指定し、そのファイルの内容をコンソールに表示する。

先ほどの演習の実行例で作成したファイルを読み込むと、次のようになる。

ファイル名を入力:U:/pr2201.dat
名前:ほげほげ
得点:920

また、このプログラムでは、読み込もうとしたファイルが存在しなかった場合にファイルが開けなかったことを表示してプログラムを終了させる。例えば、ファイル名を入力する場面で存在しないファイルを指定した場合、次のようになる。

ファイル名を入力:U:/notfound.dat
U:/notfound.datが見つかりません

擬似コードの作成

「プログラム全体」の擬似コード

プログラム全体の擬似コードは以下のようにする。

プログラム全体
    print "ファイル名を入力:"
    loadfile = コンソール入力 (String)
    if loadfile が見つからない
        print loadfile + "が見つかりません", 改行
        return
    name <- loadfile 内に格納された名前
    score <- loadfile 内に格納された得点
    if loadfile の読み込み中にエラーが発生しなかった
        print "名前:" + name, 改行
        print "得点:" + score, 改行
    else (loadfile の読み込み中にエラーが発生した)
        print "ファイル読み込み中にエラーが発生", 改行
        return

骨格の作成

クラスの作成

以下の手順で、パッケージ「j2.lesson09」に「SimpleDeserializer」クラスを作成する。

  1. 先ほど作成したパッケージ 「j2.lesson09」の上で右クリック
  2. マウスカーソルを「新規」に合わせる
  3. 「クラス」をクリック
  4. クラス名は SimpleDeserializer とする。

擬似コードの貼り付け (骨格のみ)

作成したクラスに、各擬似コードの名前を貼り付ける。ただし、「プログラム全体」ではファイルやコンソールからの入力を行っているため、import java.io.*; もつける。

package j2.lesson09;

import java.io.*;

public class SimpleDeserializer {
    // プログラム全体
}

import は個別に行ってもよい。

mainメソッドの作成 (骨格のみ)

擬似コード「プログラム全体」に合わせて、クラス「SimpleDeserializer」内にpublic static void main(String[] args) から始まるメソッドを作成する。ただし、擬似コード「プログラム全体」で使う API は IOException を発生させる可能性があるため、throws で指定しておく。

java.io.FileNotFoundException に関しては、以下の擬似コードの部分で捕捉するため、throws には指定しない (そもそも、IOException の子クラスであるため throws で指定しなくても関係ない)。

if loadfile が見つからない
    print loadfile + "が見つかりません", 改行
    return

全体の骨格

ここまでのプログラムの骨格は以下のようになる。

package j2.lesson09;

import java.io.*;

public class SimpleDeserializer {
    // プログラム全体
    public static void main(String[] args) throws IOException {
    }
}

骨格テスト

ここまでの作業をCtrl+Sを押して保存し、コンパイルを行う (保存時に自動で行われる)。ここでエラーが発生していたら文法エラーなので見直す。

「SimpleDeserializerに対する骨格テスト」を実行する。

骨格テストを行った際に緑のバーが表示されれば、外側から見たプログラムの骨格は正しくなっている。

赤いバーが表示された場合、メッセージを元にプログラムを見直すこと。修正を行い、Ctrl+Sで保存した後に「Run」ボタンをクリックする。

メッセージ 詳細
(クラス名), existence j2.lesson09 に対象のクラスが存在していない。パッケージやクラス名を確認
(メソッド名), existence 指定されたメソッドが存在しない
(メソッド名), public メソッドを作る際に public が抜けている
(メソッド名), static メソッドを作る際に static が抜けている
(メソッド名), type <T> メソッドを作る際に戻り値の型を間違えている (正しくは <T>)
(メソッド名), throws java.io.IOException メソッドを作る際に throws IOException が抜けている

プログラムへの変換

先ほど作成した SimpleDeserializer クラスの main メソッドの中身を記述する。

まずは擬似コードをコメントとして貼り付ける。

// プログラム全体
public static void main(String[] args) throws IOException {
    // print "ファイル名を入力:"
    // loadfile = コンソール入力 (String)
    // if loadfile が見つからない
        // print loadfile + "が見つかりません", 改行
        // return
    // name <- loadfile 内に格納された名前
    // score <- loadfile 内に格納された得点
    // if loadfile の読み込み中にエラーが発生しなかった
        // print "名前:" + name, 改行
        // print "得点:" + score, 改行
    // else (loadfile の読み込み中にエラーが発生した)
        // print "ファイル読み込み中にエラーが発生", 改行
        // return
}

コンソール入力

擬似コードの下記の部分は、今までどおり入力を要求する文章を表示し、コンソール入力を行うだけなので問題ない。

    print "ファイル名を入力:"
    loadfile = コンソール入力 (String)

これまでの知識で擬似コードを簡単に変換できる。

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
// print "ファイル名を入力:"
System.out.print("ファイル名を入力:");
// loadfile = コンソール入力 (String)
String loadfile = reader.readLine();

ファイルが見つからなかった場合の処理

擬似コードの次の部分では、ファイルが見つからなかった場合の処理を記述している。

if loadfile が見つからない
    print loadfile + "が見つかりません", 改行
    return

これ以降のプログラムでファイルを読み込み用に開く必要があるため、ファイルを FileInputStream クラスを用いて開いてしまって、その際に発生する FileNotFoundException を捕捉するのが楽である。

また、このプログラムでは SimpleSerializer で作成したファイルを読み込むため、様々なデータ型の値を読み込む必要がある。そこで、DataInputStream クラスを使う。

そのため、次のようなコードが書ける。

// #ファイルを開いてしまう
DataInputStream in;
try {
    in = new DataInputStream(new BufferedInputStream(new FileInputStream(loadfile)));
}
// if loadfile が見つからない
catch (FileNotFoundException e) {
    // print loadfile + "が見つかりません", 改行
    System.out.println(loadfile + "が見つかりません");
    // return
    return;
}

上記の

new DataInputStream(new BufferedInputStream(new FileInputStream(loadfile)))

と、ストリームをいくつも接続しているのは、SimpleSerializer の時と同じ理由である。ファイル操作は低速であるためにバッファ付き入力 BufferedInputStream と接続し、さらに様々なデータ型を扱うために DataInputStream を接続している。

ファイルを開いたので、ファイルを閉じる処理も一緒に書いてしまう。

...
try {
}
finally {
    in.close();
}

ファイルを操作する場合は、try 節の中にプログラムを書くことになる。

ファイルの内容を読み出す処理

擬似コードの次の部分では、ファイル内からデータを取り出している

name <- loadfile 内に格納された名前
score <- loadfile 内に格納された得点

「loadfile 内に格納された~」という表現は、「loadfile が指すファイルの内容を読み取る」ということである。loadfile が指すファイルを読み取るには、先ほど作成したファイルに接続されたストリームからデータを読み出せばよい

Serializer では、名前 (String), 得点 (int) の順にデータを書き出していたので、同じ順序かつ同じ形式でデータを読み出してやればよい。

// name <- loadfile 内に格納された名前
name = in.readUTF();
// score <- loadfile 内に格納された得点
score = in.readInt();

正常処理と例外処理

擬似コードの最後の部分では、ファイルからデータを読み込む処理を正常に行えたかどうかで表示するメッセージを変えている。

if loadfile の読み込み中にエラーが発生しなかった
    print "名前:" + name, 改行
    print "得点:" + score, 改行
else (loadfile の読み込み中にエラーが発生した)
    print "ファイル読み込み中にエラーが発生", 改行
    return

これも、例外の機構を持つ Java では、if-else 文で書き表すことができない。先ほどと同様に、次のパターンを使う。

try {
    <例外が発生するかもしれない処理>
    <正常処理>
}
catch((例外のタイプ) e) {
    <例外処理>
}

ここで、わざわざ try 節を新しく用意する必要はない。先ほど、ファイルを閉じる処理を作成する際に

try {
}
finally {
    in.close();
}

というプログラムを書いているため、ここの try に catch をつけてやればよい。

上記をまとめると、次のようなプログラムが書ける。

try {
    // name <- loadfile 内に格納された名前
    name = in.readUTF();
    // score <- loadfile 内に格納された得点
    score = in.readInt();
    // if loadfile の読み込み中にエラーが発生しなかった
    // print "名前:" + name, 改行
    System.out.println("名前:" + name);
    // print "得点:" + score, 改行
    System.out.println("得点:" + score);
}
// else (loadfile の読み込み中にエラーが発生した)
catch (IOException e) {
    // print "ファイル読み込み中にエラーが発生", 改行
    System.out.println("ファイル読み込み中にエラーが発生");
    // return
    return;
}
finally {
    in.close();
}

プログラムの実行

プログラムを実行する。

入力に先ほど作成したファイル "U:/pr2201.dat"と与えると、次のように表示される。

ファイル名を入力:U:/pr2201.dat
名前:ほげほげ
得点:920

また、存在しないファイル "U:\notfound.dat" を指定すると、次のように表示される。

ファイル名を入力:U:/notfound.dat
U:/notfound.datが見つかりません

機能テスト

ここまでの作業をCtrl+Sを押して保存し、コンパイルを行う (保存時に自動で行われる)。ここでエラーが発生していたら文法エラーなので見直す。

「SimpleDeserializerに対する機能テスト」を実行する。

赤いバーが表示された場合、メッセージを元にプログラムを見直すこと。修正を行い、Ctrl+Sで保存した後に「Run」ボタンをクリックする。

メッセージ 詳細
期待された結果と異なります 出力された結果が期待された値と異なる。

機能テストの項目

項目名 テストの内容
sample .temp/pr02.dat を実行例と同じ内容で作成し、それを読み出す (終了後に削除している)

プログラム全体

SimpleDeserializer 全体を記述しておく。

package j2.lesson09;

import java.io.*;

public class SimpleDeserializer {
    // プログラム全体
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        // print "ファイル名を入力:"
        System.out.print("ファイル名を入力:");
        // loadfile = コンソール入力 (String)
        String loadfile = reader.readLine();
        // #ファイルを開いてしまう
        DataInputStream in;
        try {
            in = new DataInputStream(new BufferedInputStream(new FileInputStream(loadfile)));
        }
        // if loadfile が見つからない
        catch (FileNotFoundException e) {
            // print loadfile + "が見つかりません", 改行
            System.out.println(loadfile + "が見つかりません");
            // return
            return;
        }
        String name;
        int score;
        try {
            // name <- loadfile 内に格納された名前
            name = in.readUTF();
            // score <- loadfile 内に格納された得点
            score = in.readInt();
            // if loadfile の読み込み中にエラーが発生しなかった
            // print "名前:" + name, 改行
            System.out.println("名前:" + name);
            // print "得点:" + score, 改行
            System.out.println("得点:" + score);
        }
        // else (loadfile の読み込み中にエラーが発生した)
        catch (IOException e) {
            // print "ファイル読み込み中にエラーが発生", 改行
            System.out.println("ファイル読み込み中にエラーが発生");
            // return
            return;
        }
        finally {
            in.close();
        }
    }
}