LoginSignup
4
2

More than 5 years have passed since last update.

Java 入出力 memo (Oracle Java8 Gold 試験対策)

Posted at

Goldの出題範囲がとても広い(なんとしても2018/9中に取りたい)。。
今回のメモはこれ。

  • Fileクラス
  • ストリーム
  • シリアライズ
  • コンソール

Fileクラス

サンプル実行のために事前にファイル作成しておく。

mkdir /tmp/dir
touch /tmp/dir/hoge.txt
touch /tmp/dir/fuga.txt
mkdir /tmp/dir/subdir
touch /tmp/a.txt
touch /tmp/dir/x.txt
import java.io.File;

public class InOutFileSample {
    public static void main(String[] args) {

        // Fileオブジェクトの生成
        File f1 = new File("/tmp/dir");
        File f2 = new File("tmp", "a.txt");
        File f3 = new File(f1, "x.txt");

        for (File f : f1.listFiles()) { // f1ディレクトリ内のファイル群を取得

            if (f.isFile()) { // ファイルだった場合
                System.out.println("File: " + f.getName());
            } else if (f.isDirectory()) { // ディレクトリだった場合
                System.out.println("Directory: " + f.getName());
            }
        }

        // 絶対パス確認
        System.out.println("f1 absolute path: " + f1.getAbsolutePath());
        System.out.println("f2 absolute path: " + f2.getAbsolutePath());
        System.out.println("f3 absolute path: " + f2.getAbsolutePath());

    }
}

ストリーム

4つの基本的なストリーム

  • 入力ストリーム(InputStream)
    • データの読み込み
  • 出力ストリーム(OutputStream)
    • データの書き込み
  • バイトストリーム
    • byte単位で読み書きするストリーム
  • キャラクタストリーム
    • char単位で読み書きするストリーム
バイトストリーム キャラクタストリーム
出力ストリーム OutputStream Writer
入力ストリーム InputStream Reader

XXStreamのStreamがついてなければキャラクタストリーム。

主なバイトストリーム

クラス名 説明
FileInputStream ファイルからbyte単位の読み出しのためのストリーム
FileOutputStream ファイルに対してbyte単位の書き出しするためのストリーム
DataInputStream 基本データ型のデータを読み出せるストリーム
DataOutputStream 基本データ型のデータを書き出せるストリーム

主なキャラクタストリーム

クラス名 説明
FileReader ファイルからchar単位の読み込みをするためのストリーム
FileWriter ファイルに対してchar単位の書き込みをするためのストリーム
BufferedReader 基本データ型のデータを読み込むためのストリーム
BufferedWriter 基本データ型のデータを書き出すためのストリーム

FileInputStream/FileOutputStream

バイトストリームのFileInputStreamFileOutputStreamを使った実装。

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileInputOutputStreamSsample {
    public static void main(String[] args) {

        try (FileOutputStream fos = new FileOutputStream("/tmp/lesson.txt");
             FileInputStream fis = new FileInputStream("/tmp/lesson.txt")) {

            // ファイルへの書き込み
            fos.write(0);
            fos.write("makio".getBytes());
            fos.write(99);

            // ファイルから読み込み
            int data = 0;
            while ((data = fis.read()) != -1) { // -1を返すまでreadメソッドでバイト単位の読み込み
                System.out.print(data + " ");
            }

        } catch (FileNotFoundException e) {
            System.out.println("ファイルがありません。");
        } catch (IOException e) {
            System.out.println("ファイルの読み書きで失敗");
        }
    }
}
0 109 97 107 105 111 99 

なお、FileOutputStreamでファイルに対して追記したい場合は、以下のようにする。

// これだと新規作成になる。
FileOutputStream("/tmp/lesson.txt")

// 第二引数にtrueを与えると追記になる。
FileOutputStream("/tmp/lesson.txt", true)

DataInputStream/DataOutputStream

バイトストリームのDataInputStreamDataOutputStreamを使った実装。

このストリームは単体では利用できないので、他のストリームと組み合わせて利用する。

import java.io.*;

public class DataInputOutputStreamSample {

    public static void main(String[] args) {

        try(DataOutputStream dos =
                    new DataOutputStream(new FileOutputStream("/tmp/lesson.txt"));
            DataInputStream dis =
                    new DataInputStream(new FileInputStream("/tmp/lesson.txt"))) {

            // ファイルへの書き込み
            dos.writeInt(100);
            dos.writeUTF("makio");
            dos.writeUTF("ほげほげほげ");

            // ファイルから読み込み
            System.out.println(dis.readInt());
            System.out.println(dis.readUTF());
            System.out.println(dis.readUTF());

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
100
makio
ほげほげほげ

FileReader/FileWriter

キャラクタストリームのFileReaderFileWriterクラスの利用例。
DataInputStream/DataOutputStreamと異なり、自動でエンコーディングしてくれる。

import java.io.*;

public class FileReaderWriterSample {
    public static void main(String[] args) {
        try (FileWriter fw = new FileWriter(new File("/tmp/lesson.txt"));
             FileReader fr = new FileReader(new File("/tmp/lesson.txt"))) {

            // ファイルへの書き込み
            fw.write("ほげほげほほげ");
            fw.flush();

            // ファイルから読み込み
            int i = 0;
            while((i = fr.read()) != -1) {
                // キャラクタ型にキャストして出力
                System.out.print((char) i);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
ほげほげほほげ

BufferedReader/BufferedWriter

キャラクタストリームのBufferedReaderBufferedWriterクラスの利用例。

文字列をブロック単位で読み書きするためのストリーム。
バッファリングしながら入出力するので、効率がいい。

import java.io.*;

public class BufferedReaderWriterSample {
    public static void main(String[] args) {
        try (BufferedWriter bw = new BufferedWriter(new FileWriter(new File("/tmp/lesson.txt")));
             BufferedReader br = new BufferedReader(new FileReader(new File("/tmp/lesson.txt")))) {

            // ファイルへの書き込み
            bw.write("Good morning!");
            bw.newLine();
            bw.write("Good afternoon!");
            bw.newLine();
            bw.write("Good evening!");
            bw.flush(); // flushで即時反映

            // ファイルから読み込み
            String data = null;
            while ((data = br.readLine()) != null) { // readLineメソッドはファイルの最後になると、nullを返す。
                System.out.println(data);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
Good morning!
Good afternoon!
Good evening!

シリアライズ

  • シリアライズ
    • オブジェクトを出力ストリームに書き出すこと
    • 直列化ともいう。
  • デシリアライズ
    • シリアライズされたオブジェクトを読み込んでメモリ上の復元すること
    • 直列化復元ともいう。

シリアライズの方法

ここではUserクラスのオブジェクトをObjectInputStreamObjectOutputStreamを使ってファイルに書き出して復元する。

import java.io.*;

/**
 * シリアライズ対象のUserクラス
 * Serializableインタフェースはメソッドをもたない
 */
class User implements Serializable {
    private int id;
    private String name;

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

public class SerializeDeseriazlieSample {

    public static void main(String[] args) {
        User writeUser = new User(1000, "Makio");

        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/tmp/user_object.txt"));
             ObjectInputStream ois = new ObjectInputStream(new FileInputStream("/tmp/user_object.txt"))) {

            // オブジェクトの書き込み シリアライズ
            oos.writeObject(writeUser);
            oos.flush();

            // オブジェクトの読み込み デシリアライズ
            User readUser = (User)ois.readObject(); // Userにキャストしないといけない。
            System.out.format("id: %d, name: %s", readUser.getId(), readUser.getName());

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }
}
id: 1000, name: Makio

シリアライズの注意点 

考えて見れば当たり前ことばかりだけど制約事項が多い。

  • 配列またはコレクションをシリアライズする場合は、その要素のそれぞれがシリアライズ可能でないといけない。
  • シリアライズされたオブジェクトが参照しているオブジェクトもシリアライズ可能でないといけない.
  • static変数およびtansient指定された変数はシリアライズ対象外になる。
  • スーパークラスをシリアライズ対象としていればサブクラスも暗黙的にシリアライズ対象になる。
  • サブクラスがシリアライズ対象の場合、スーパークラスはデシリアライズの際にインスタンス化される。

コンソール

コンソールから読み書きするためにはConsoleオブジェクトを生成してコンソールのストリームに読み書きする。

import java.io.Console;
import java.io.PrintWriter;

public class ConsoleSample {
    public static void main(String[] args) {
        // System.console()で一意のConsoleオブジェクトを取得
        // コンソールが使用できない場合はconsole()メソッドはnullになる。
        Console console = System.console();

        // キャラクタストリームのPrintWriterオブジェクトを生成
        PrintWriter pw = console.writer();

        while (true) {
            String str = console.readLine();
            if (str.equals("end")) {
                break;
            }
            pw.append("input data: " + str);
            pw.flush();
        }

    }
}
4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2