第22週目課題

課題2201

(バイナリ) ファイルを別のファイルにコピーするプログラム BinaryCopier クラスをパッケージ j2.lesson09 に作成しなさい。

このプログラムは、二つのファイル名を入力し、一つ目に指定したバイナリファイルの内容を二つ目に指定したファイルにコピーする。課題2102と似ているが、このプログラムはテキストファイルのみでなくバイナリファイルも扱うことができる

例えば、U:\ex2201sample.dat (ex2201sample.dat) という名前の次の内容を持つファイルがあったとする。


このプログラムを実行し、"U:/ex2201sample.dat", "U:/ex2201copy.dat" と入力すると、次のように表示される。

コピー元のファイル名を入力:U:/ex2201sample.dat
コピー先のファイル名を入力:U:/ex2201copy.dat
U:/ex2201sample.datからU:/ex2201copy.datにコピーしました。

さらに、上記のように表示された後、U: ドライブには ex2201copy.dat というファイルが作成され、次のような内容になっている。


次の擬似コードに従った出力をすること。

print "コピー元のファイル名を入力:"
src = コンソール入力 (String)
print "コピー先のファイル名を入力:"
dst = コンソール入力 (String)
copy(src, dst)
if コピー中に例外が発生しなかった
    print src + "から" + dst + "にコピーしました。", 改行
else
    print src + "から" + dst + "にコピーできませんでした。", 改行

上記のプログラムは、j2.lesson09.BinaryCopier クラスの main メソッドに記述すること。

また、擬似コード中に現れる copy(src, dst) というメソッドは、次のようなメソッドである。

public static void copy(java.lang.String src,
                        java.lang.String dst)
                 throws java.io.IOException
srcからdstにバイナリファイルの内容をコピーする。
このメソッド内で例外 FileNotFoundException, IOException が発生した場合は、
このメソッド内で捕捉せずに呼び出し元で処理する必要がある。 

パラメータ: 
    src - コピー元のファイル名
    dst - コピー先のファイル名 
例外: 
    java.io.IOException - コピーしようとした際に例外が発生した場合

上記の仕様を持つメソッドも j2.lesson09.BinaryCopier クラス内に作成し、main 内の擬似コードの該当する部分から呼び出すこと。

手順

指定した箇所で必ずテストを行うこと。

  1. 詳細な擬似コードを作成する
  2. パッケージ j2.lesson09 にクラス BinaryCopier を作成
  3. 必要なメソッドを作成する
  4. テスト項目「BinaryCopierに対する骨格テスト」をパス
  5. それぞれのメソッドにプログラムを書く
  6. テスト項目「BinaryCopierに対する機能テスト」をパス

ヒント

copy メソッドの「このメソッド内で捕捉せずに呼び出し元で処理する必要がある」とはつまり、「このメソッドでは例外処理を行わずに呼び出し元に任せる」という意味である。そのような場合は throws で発生する例外 (RuntimeException を除く) を指定し、そのメソッド内では例外を catch しなければよい。

テストの失敗メッセージ

骨格テスト

メッセージ 詳細
(クラス名), existence パッケージ内に課題で指定したクラスが存在していない。パッケージやクラス名を確認
(メンバ名), existence 指定されたメンバが存在しない
(メンバ名), public メンバを作る際に public の指定がない
(メンバ名), static メンバを作る際に static の指定がない
(メンバ名), type <T> メンバを作る際に型の指定を間違っている。正しくは <T>

機能テスト

メッセージ 詳細
期待された結果と異なります 出力された結果が期待された値と異なる。「期待された値」と「実際の値」を比較し確認。他にも直接プログラムを実行して結果を調べたり、エラーメッセージの2行目にあるat以下を参考にプログラムを見直す
ファイルが開けません コピーしたファイルが開けなかった場合

機能テストの項目

テスト失敗時に「Results」の欄の左側に出る「test~」は、テストの項目名を表している。

項目名 詳細
sample1 ".temp/ex2201sample1.dat" の内容を ".temp/ex2201copy.dat" にコピー
sample2 存在しないファイル ".temp/ex2201sample2.dat" の内容を ".temp/ex2201copy.dat" にコピー
sample3 ".temp/ex2201sample3.dat" の内容を書き込めないファイル ".temp/ex2201copy.dir" にコピー

課題2202

ファイル内に書かれている数値を読み出し、その総和を表示するプログラム TotalInBinaryFile クラスをパッケージ j2.lesson09 に作成しなさい。

読み取ることができるファイルの形式は、次のようなファイルである。

まず、データを 1 バイトだけ読み、その値を「形式を表す値」とする。形式を表す値が 1 ならば次の 4 バイトは int 型の値が格納されていて、形式を表す値が 2 ならば次の 8 バイトは double 型の値が格納されている。この 1 バイト + (4 または 8 バイト) で一つの数値を表し、そのようなデータがいくつも並んでいる。

形式を表す値を読もうとした際にファイルの終端に達したら、プログラムを終了させる。また、形式を表す値が 1 または 2 ではない場合はエラーとなる。

例えば、U:\ex2202sample.dat に次のようなファイルが存在したとする。

形式を表す値 数値
1 50000
2 3.1415926535

このファイルを作るためのプログラムは、以下のようになる。

String filename = "U:/ex2201sample.dat";
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(filename)));
try {
    // 5000
    out.write(1);
    out.writeInt(5000);
    // 3.1415926535
    out.write(2);
    out.writeDouble(3.1415926535);
}
finally {
    out.close();
}

課題のプログラムでは、上記のプログラムを実行して得られるようなファイルを読み込み、格納されている int 型の値や double 型の値を取得し、その合計値を表示する。

このプログラムを実行し、コンソールに "U:/ex2202sample.dat" と入力すると、次のように表示される。

ファイル名を入力:U:/ex2202sample.dat
合計は5003.1415926535

また、このプログラムは独自に定義した例外 j2.lesson09.IllegalFileFormatException をスローする可能性がある。この例外クラスは次のようなクラスである (パッケージ内にコピーして使用せよ)。

package j2.lesson09;

public class IllegalFileFormatException extends Exception {
    // メッセージを指定して、例外インスタンスを作成する。
    // message - メッセージ
    public IllegalFileFormatException(String message) {
        super(message);
    }
}

形式を表す値は必ず 1 または 2 で、それ以外の値を読み込んだ場合は次のように例外をスローしてプログラムが終了させること (この際のメッセージは何でもよい)。

ファイル名を入力:U:/ex2202unknown.dat
Exception in thread "main" j2.lesson09.IllegalFileFormatException: 不明なコード
    at j2.lesson09.TotalInBinaryFile.main(TotalInBinaryFile.java:62)

上記の "U:\ex2202unknown.dat" (ex2202unknown.dat) は、形式を表す値が 3 になっているデータを含むファイルである。

形式を表す値は必ず 1 バイトで、その値が 1 ならばその次には 4 バイトのデータが、その値が 2 ならばその次には 8 バイトのデータが必ず存在しなければならない。例えば、4 バイト (01 00 00 00) からなるファイル "U:\ex2202illegaleof.dat" (ex2202illegaleof.dat) を読み込んだ場合、int 型の値を読んでいる最中にファイルの終端に達してしまうため、次のように例外をスローしてプログラムを終了させること (この際のメッセージは何でもよい)。

ファイル名を入力:U:/ex2202illegaleof.dat
Exception in thread "main" j2.lesson09.IllegalFileFormatException: 不正なファイルの終端
    at j2.lesson09.TotalInBinaryFile.main(TotalInBinaryFile.java:69)

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

ファイル名を入力:U:/ex2202notfound.dat
U:/ex2202notfound.datが開けませんでした。

ファイルが見つからない場合や、ファイルの形式が不正である場合以外に IOException が発生した場合は、catch 節で捕捉しないでよい (つまり、このメソッドには throws IOException の指定をすればよい)。

プログラム全体の擬似コードは次の通りである。擬似コードに従った表示を行うこと。

print "ファイル名を入力:"
filename = コンソール入力 (String)
file = filename のファイルを読み込み用に開く
if filename が開けない
    print filename + "が開けませんでした。", 改行
    プログラムを終了
total = filename が指すファイル内に格納されている各数値の合計
if 1 でも 2 でもない「形式を表す値」を含んでいる
    throw IllegalFileFormatException
if データを読み込んでいる途中でファイルの終端に達した
    throw IllegalFileFormatException
if ファイル読み込み中に例外が発生しなかった
    print "合計は" + total

上記のプログラムは、j2.lesson09.TotalInBinaryFile クラスの main メソッドに記述すること。

手順

指定した箇所で必ずテストを行うこと。

  1. 詳細な擬似コードを作成する
  2. パッケージ j2.lesson09 にクラス TotalInBinaryFile を作成
  3. main メソッドを作成する
  4. テスト項目「TotalInBinaryに対する骨格テスト」をパス
  5. main メソッドにプログラムを書く
  6. テスト項目「TotalInBinaryに対する機能テスト」をパス

ヒント

java.io.DataInputStream を使う。このクラスが持つメソッドのいくつかは、java.io.EOFException という例外をスローする。

テストの失敗メッセージ

骨格テスト

メッセージ 詳細
(クラス名), existence パッケージ内に課題で指定したクラスが存在していない。パッケージやクラス名を確認
(メンバ名), existence 指定されたメンバが存在しない
(メンバ名), public メンバを作る際に public の指定がない
(メンバ名), static メンバを作る際に static の指定がない
(メンバ名), type <T> メンバを作る際に型の指定を間違っている。正しくは <T>
(メンバ名), throws <T> メンバを作る際に throws <T> の指定がない

機能テスト

メッセージ 詳細
期待された結果と異なります 出力された結果が期待された値と異なる。「期待された値」と「実際の値」を比較し確認。他にも直接プログラムを実行して結果を調べたり、エラーメッセージの2行目にあるat以下を参考にプログラムを見直す
<T> がスローされませんでした 例外 <T> がスローされるべき場面でスローされなかった

機能テストの項目

テスト失敗時に「Results」の欄の左側に出る「test~」は、テストの項目名を表している。

項目名 詳細
sample1 "1" というファイルを .temp/ex2202sample1.dat に作成
sample2 "1.0" というファイルを .temp/ex2202sample2.dat に作成
sample3 "1", "2.0", "3", "4.0" というファイルを .temp/ex2202sample3.dat に作成
unkwnon ex2202unknown.dat と同じファイルを .temp/ex2202unknown.dat に作成
illegaleof ex2202illegaleof.dat と同じファイルを .temp/ex2202illegaleof.dat に作成
notfound 存在しないファイルを指定

課題2203 (optional)

バイナリデータとして書かれた学生の得点一覧ファイルを読み出すクラス ScoreDatabase をパッケージ j2.lesson09 に作成しなさい。

このプログラムは、課題2103にある ScoreDatabase クラスと非常に似ている。ただし、扱うファイルの形式がバイナリデータとなっている。

このバイナリデータは、データの先頭から順に次のような形式である。

ただし、学籍番号や名前が指定された文字数に満たない場合、末尾は (char) 0 で埋められている。

このプログラムの一部を掲載する。このプログラム (クラス) を j2.lesson09 パッケージ内にコピーし、これにコンストラクタやメソッドを書き加えること。

2005/11/24 23:49 名前の長さが char*8 になっていたのを char*10 に修正。ScoreDatabase.save(String) も修正してください。修正に伴い、ダウンロードできるデータも訂正しました。

package j2.lesson09;

import java.io.*;
import java.util.*;

public class ScoreDatabase {

    private final List students;

    public void save(String filename) throws IOException {
        DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(filename)));
        try {
            // 最初に個数を int 型で書き込む
            out.writeInt(this.students.size());
            for (int i = 0; i < this.students.size(); i++) {
                Student std = (Student) this.students.get(i);
                // id を書き込み (char*4, 8bytes)
                char[] id = std.getId().toCharArray();
                for (int j = 0; j < 4; j++) {
                    if (j < id.length) {
                        out.writeChar(id[i]);
                    }
                    else {
                        out.writeChar((char) 0);
                    }
                }
                // name を書き込み (char*10, 20bytes)
                char[] name = std.getName().toCharArray();
                for (int j = 0; j < 10; j++) {
                    if (j < name.length) {
                        out.writeChar(name[i]);
                    }
                    else {
                        out.writeChar((char) 0);
                    }
                }
                // score を書き込み (int, 4bytes)
                out.writeInt(std.getScore());
            }
        }
        finally {
            out.close();
        }
    }
}

上記にある Student クラスは次のようなクラスである。このクラスを j2.lesson09 パッケージ内に作成すること。上記 j2.lesson09.ScoreDatabase を先に作成すると j2.lesson08.Student クラスが import されてしまう可能性があるため、import j2.lesson08.Student の指定があれば削除すること

package j2.lesson09;

public class Student {

    private final String id;
    private final String name;
    private final int score;
    
    // 学生インスタンスを作成する
    // - id この学生の学籍番号
    // - name この学生の名前
    // - score この学生の得点
    public Student(String id, String name, int score) {
        super();
        this.id = id;
        this.name = name;
        this.score = score;
    }

    // この学生の学籍番号を取得する
    public String getId() {
        return this.id;
    }

    // この学生の名前を取得する
    public String getName() {
        return this.name;
    }

    // この学生の得点を取得する
    public int getScore() {
        return this.score;
    }

    // この学生の成績を取得する
    public char getGrade() {
        if (this.score >= 80) {
            return 'A';
        }
        else if (this.score >= 70) {
            return 'B';
        }
        else if (this.score >= 60) {
            return 'C';
        }
        else {
            return 'D';
        }
    }

    // この学生の文字列表現を取得する
    public String toString() {
        return "id=" + getId() + ", name=" + getName() +
               ", score=" + getScore() + ", grade=" + getGrade();
    }
}

ScoreDatabase クラスには、次のようなコンストラクタやメソッドを記述すること。

ファイルを読み込む場合は、このコンストラクタ内で読み込むこと。それ以外のメソッドでは throws IOException を発生させてはならない。また、このコンストラクタ内で例外が発生した場合は、捕捉せずに throws で呼び出し元に例外処理を任せること。

このコンストラクタで読み込めるデータの形式は、save メソッドで作成できるファイルと同じ形式であるものとする。正しい形式を持った "hoge.dat" というファイルが存在したとして、

ScoreDatabase sdb = new ScoreDatabase("hoge.dat");
sdb.save("foo.dat");

上記のようなプログラムを書いた際の動作として、hoge.dat と foo.dat の中身が同じになるようようにすること。

「Student 型を格納している List」というのは、このメソッドを呼び出した結果、返ってくる List の各要素が Student クラスのインスタンスであるということを指す。

取得する学生の成績は、Student クラスのインスタンスメソッド getGrade() の結果と等しくなるようにすること。また、指定した成績を持つ学生がいない場合は、長さ 0 の List を返すこと。

プログラムの例

まず、ex2203test.dat をダウンロードし、U:\ex2203test.dat に置く。これは、課題2103 の形式で表すと次のような内容を持つデータである。

0000,ほげ1,100
0002,ふー2,80
0005,ばー3,60
0009,ほげ4,40
0010,ふー5,20

このファイルを読む、簡単なプログラムを書いてみる。

public static void main(String[] args) {
    ScoreDatabase sdb;
    try {
        sdb = new ScoreDatabase("U:/ex2203test.dat");
    }
    catch (IOException e) {
        System.out.println("U:/ex2203test.datが開けません");
        return;
    }
    List all = sdb.getAllStudent();
    System.out.println("全体の人数=" + all.size());
    List as = sdb.getStudents('A');
    printList('A', as);
    List bs = sdb.getStudents('B');
    printList('B', bs);
    List cs = sdb.getStudents('C');
    printList('C', cs);
    List ds = sdb.getStudents('D');
    printList('D', ds);
}

private static void printList(char grade, List list) {
    System.out.println(grade + "の学生:");
    for (int i = 0; i < list.size(); i++) {
        System.out.println("  " + list.get(i));
    }
}

上記のプログラムを実行すると、次のように表示される。

全体の人数=5
Aの学生:
  id=0000, name=ほげ1, score=100, grade=A
  id=0002, name=ふー2, score=80, grade=A
Bの学生:
Cの学生:
  id=0005, name=ばー3, score=60, grade=C
Dの学生:
  id=0009, name=ほげ4, score=40, grade=D
  id=0010, name=ふー5, score=20, grade=D

手順

指定した箇所で必ずテストを行うこと。

  1. パッケージ j2.lesson09 にクラス Student を作成
  2. 詳細な擬似コードを作成する
  3. パッケージ j2.lesson09 にクラス ScoreDatabase を作成
  4. 指定したコンストラクタやインスタンスメソッドを作成する
  5. テスト項目「ScoreDatabaseに対する骨格テスト」をパス
  6. 各コンストラクタやメソッドにプログラムを書く
  7. テスト項目「ScoreDatabaseに対する単体テスト」をパス

ヒント

char 型の配列から、一部分を取り出して String 型に変換する場合、java.lang.String クラスのクラスメソッド valueOf(char[], int, int) が便利である。

また、ある文字 c が (char) 0 と同じ値を持つか判定する場合、「if (c == (char) 0) ..」のように書けばよい (0 を char にキャストしなくても同じ意味である)。

テストの失敗メッセージ

骨格テスト

メッセージ 詳細
(クラス名), existence パッケージ内に課題で指定したクラスが存在していない。パッケージやクラス名を確認
(メンバ名), existence 指定されたメンバが存在しない
(メンバ名), public メンバを作る際に public の指定がない
(メンバ名), not static メンバを作る際に static が余計についている
(メンバ名), type <T> メンバを作る際に型の指定を間違っている。正しくは <T>

単体テスト

メッセージ 詳細
期待された結果と異なります メソッドを起動した結果が期待された結果と異なる。テスト項目を参照
例外 <E> がスローされませんでした 例外 <E> が発生すべき場面で例外が発生しなかった

単体テストの項目

テスト失敗時に「Results」の欄の左側に出る「test~」は、テストの項目名を表している。

項目名 詳細
ScoreDatabase_sample1 new ScoreDatabase(".temp/ex2203sample1.dat")
ScoreDatabase_sample2 new ScoreDatabase(".temp/ex2203sample2.dat")
ScoreDatabase_sample4 new ScoreDatabase(".temp/ex2203sample3.dat")
getAllStudent_sample1 new ScoreDatabase(".temp/ex2203sample1.dat").getAllStudent()
getAllStudent_sample2 new ScoreDatabase(".temp/ex2203sample2.dat").getAllStudent()
getStudents_A_sample1 new ScoreDatabase(".temp/ex2203sample1.dat").getStudents('A')
getStudents_A_sample2 new ScoreDatabase(".temp/ex2203sample2.dat").getStudents('A')
getStudents_B_sample1 new ScoreDatabase(".temp/ex2203sample1.dat").getStudents('B')
getStudents_B_sample2 new ScoreDatabase(".temp/ex2203sample2.dat").getStudents('B')
getStudents_C_sample1 new ScoreDatabase(".temp/ex2203sample1.dat").getStudents('C')
getStudents_C_sample2 new ScoreDatabase(".temp/ex2203sample2.dat").getStudents('C')
getStudents_D_sample1 new ScoreDatabase(".temp/ex2203sample1.dat").getStudents('D')
getStudents_D_sample2 new ScoreDatabase(".temp/ex2203sample2.dat").getStudents('D')
getStudents_a_sample1 new ScoreDatabase(".temp/ex2203sample1.dat").getStudents('a')
getStudents_9_sample1 new ScoreDatabase(".temp/ex2203sample1.dat").getStudents('9')
getStudents_at_sample1 new ScoreDatabase(".temp/ex2203sample1.dat").getStudents('@')
getStudents_E_sample1 new ScoreDatabase(".temp/ex2203sample1.dat").getStudents('E')
getStudents_Z_sample1 new ScoreDatabase(".temp/ex2203sample1.dat").getStudents('Z')

それぞれのファイルの内容は以下の通りである (読みやすいように 課題2103 と同じ形式で記述している)。

0000,ほげ1,100
0002,ふー2,80
0005,ばー3,60
0009,ほげ4,40
0010,ふー5,20
0000,ほげA,100
0006,ほげC,69
0010,ふーD,30
0004,ふーB,75
0003,ほげB,79
0007,ふーC,65
0002,ばーA,80
0008,ばーC,60
0005,ばーB,70
0009,ほげD,59
0001,ふーA,90
0011,ばーD,0

課題2204 (optional)

ZIPファイルからデータを取り出すプログラム ZipUncompressor クラスをパッケージ j2.lesson09 に作成しなさい。

ZIPとは、世界で最もよく使われているファイル圧縮形式の一つで、いくつかのファイルをまとめて圧縮し、一つのファイルにすることができる。このようなファイルからデータを取り出すには専用のソフトウェアが必要で (WindowsXP には標準で ZIP ファイルの圧縮および展開ができる)、今回はこのような ZIP ファイルから圧縮されたデータを取り出すようなプログラムを製作する。

例えば、U:\ex2204hello.zip (ex2204hello.zip) というファイルに ex2204hello.txt という名前のファイルが格納されているとする。この ex2204hello.txt というファイルを取り出すには、課題のプログラムを実行して次のように入力する。

ZIP書庫ファイル名を入力:U:/ex2204hello.zip
書庫内のファイル名を入力:ex2204hello.txt
解凍先のファイル名を入力:U:/ex2204hello-uncompressed.txt
U:/ex2204hello-uncompressed.txtにコピーしました

上記のように実行すると、U:\ex2204hello-uncompressed.txt に次のような内容のテキストファイルが作成される。

Hello, world!

例ではテキストファイルを用いたが、課題では全てのバイナリファイルを扱えるように設計すること

プログラム全体の擬似コードは次の通りである。擬似コードに従った表示を行うこと。

プログラム全体
    print "ZIP書庫ファイル名を入力:"
    zip = コンソール入力 (String)
    if zip が指すファイルを読み込めない
        print zip + "が読み込めません", 改行
        return
    print "書庫内のファイル名を入力:"
    contents = コンソール入力 (String)
    if zip が指すファイル内に contents が存在しない
        print zip + "内の" + contents + "が存在しません", 改行
        return
    print "解凍先のファイル名を入力:"
    target = コンソール入力
    zip が指すファイル内の contents の内容を target に書き出す
    if 読み書き中に例外が発生しなかった
        print target + "にコピーしました", 改行
    else
        print "コピー中に例外が発生しました", 改行

実行例

先ほどの U:\ex2204hello.zip (ex2204hello.zip) を使って、いくつか例を示す。

ZIP書庫ファイル名を入力:U:/ex2204hello.zip
書庫内のファイル名を入力:ex2204hello.txt
解凍先のファイル名を入力:U:/ex2204hello-uncompressed.txt
U:/ex2204hello-uncompressed.txtにコピーしました
ZIP書庫ファイル名を入力:U:/ex2204hallo.zip
U:/ex2204hallo.zipが読み込めません
ZIP書庫ファイル名を入力:U:/ex2204hello.zip
書庫内のファイル名を入力:ex2204hallo.txt
U:/ex2204hello.zip内のex2204hallo.txtが存在しません

手順

指定した箇所で必ずテストを行うこと。

  1. パッケージ j2.lesson09 にクラス ZipUncompressor を作成
  2. 指定したインスタンスメソッドやコンストラクタを作成する
  3. テスト項目「ZipUncompressorに対する骨格テスト」をパス
  4. インスタンスメソッドやコンストラクタの中身を書く (演習と同様)
  5. main メソッドを書いて簡単なテストを行う
  6. テスト項目「ZipUncompressorに対する単体テスト」をパス

ヒント

ZIP ファイルの形式を調べて自分で解凍処理を実装してもよいが、非常に大変である。そのため、ZIP ファイルを扱うような ZIP ファイルを扱うような API を探すとよい。検索エンジンなどに Java ZIP といったキーワードを入力してみよ。

テストの失敗メッセージ

骨格テスト

メッセージ 詳細
(クラス名), existence パッケージ内に課題で指定したクラスが存在していない。パッケージやクラス名を確認
(メンバ名), existence 指定されたメンバが存在しない
(メンバ名), public メンバを作る際に public の指定がない
(メンバ名), static メンバを作る際に static の指定がない
(メンバ名), type <T> メンバを作る際に型の指定を間違っている。正しくは <T>

機能テスト

メッセージ 詳細
期待された結果と異なります 出力された結果が期待された値と異なる。「期待された値」と「実際の値」を比較し確認。他にも直接プログラムを実行して結果を調べたり、エラーメッセージの2行目にあるat以下を参考にプログラムを見直す

機能テストの項目

テスト失敗時に「Results」の欄の左側に出る「test~」は、テストの項目名を表している。

項目名 詳細
notfound 存在しないファイル .temp/ex2204.zip の内容を参照
hello_hello .temp/ex2204hello.zip!ex2204hello.txt の内容を .temp/ex2204hello.txt に展開
hello_notfound 存在しないファイル .temp/ex2204hello.zip!notfound の内容を参照
sample_ex2201 .temp/ex2204sample.zip!ex2201sample.dat の内容を .temp/ex2204sample1.dat に展開
sample_ex2202 .temp/ex2204sample.zip!ex2202sample1.dat の内容を .temp/ex2204sample2.dat に展開
sample_ex2203 .temp/ex2204sample.zip!ex2203sample1.dat の内容を .temp/ex2204sample3.dat に展開
sample_ex2204 .temp/ex2204sample.zip!ex2204hello.zip の内容を .temp/ex2204sample4.dat に展開
sample_notfound 存在しないファイル .temp/ex2204sample.zip!ex2205sample.dat の内容を参照

上記テストに出てくるZIPファイルは、次のようなファイルである。