未来エンジニア養成所Blog

プログラミングを皆に楽しんでもらうための情報をお届けします。

【Java】ファイルの入出力 Part4

title

前回に引き続きファイルの入出力についての解説です。

前回までの記事はこちら phoeducation.work phoeducation.work phoeducation.work


シリアライズ

シリアライズ直列化とも呼ばれ、入出力の際に、バイト単位や文字単位、行単位でなく、オブジェクト単位でファイルに書き込むことです。

シリアライズされたオブジェクトを読み込んでメモリ上に復元することをデシリアライズ(直列化復元)といいます。

シリアライズしたいオブジェクトはSerializableインターフェースを実装します。

Serializableインターフェースはメソッドを持たないため、オーバーライドするメソッドはありません。

オブジェクトのシリアライズは、実際にはオブジェクトが保有するインスタンス変数がシリアライズの対象となります。(static変数は対象にならなりません)

インスタンス変数を、明示的にシリアライズの対象外としたい場合、transientキーワードをつけます。

シリアライズ可能なオブジェクトはファイル間だけでなく、ネットワーク間でのやり取りにも利用されます。

オブジェクト単位で入出力を行うには、ObjectInputStreamクラスObjectOutputStreamクラスを使用します。

シリアライズ


オブジェクトの読み書き

ObjectInputStreamとObjectOutputStreamはオブジェクト単位でデータの入出力を行うクラスです。

ObjectInputStreamとObjectOutputStreamクラスを使用して、オブジェクトの入出力を行うには、そのオブジェクトがシリアライズされている必要があります。implements Serializableと記述します。


コンストラクタはInputStreamやOutputStremオブジェクトを引数に指定します。

メソッドはreadObject( )を使用すると、ObjectInputStreamからオブジェクトを読み込みます。

戻り値はObject型であるため、使用時に目的の型にキャストする必要があります。

writeObject()を使用すると、シリアライズされたオブジェクトをObjectOutputStreamに書きだすことができます。引数に指定するオブジェクトはシリアライズ可能なオブジェクトである必要があります。


【ObjectInputStreamとObjectOutputStreamのコンストラクタ】
コンストラクタ


【ObjectInputStreamとObjectOutputStreamのメソッド】
メソッド


【ObjectInputStreamとObjectOutputStreamの利用】
前回「filetext2」ファイルを作成している人はいったん削除しておきましょう。
また前回と同様にプロジェクトの中に「filesample」フォルダが必要になります。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class FileSample7 {
    public static void main(String args[]){
        Human taro = new Human("太郎", 25, 175.5);
        File file = new File("filesample¥¥filetext2.txt");
        try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
              ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))){
            oos.writeObject(taro);
            Human readtaro = (Human)ois.readObject();
            System.out.println(readtaro.getName());
            System.out.println(readtaro.getAge());
            System.out.println(readtaro.getHeight());
        }catch(ClassNotFoundException | IOException e){
            e.printStackTrace();
        }
    }
}
class Human implements Serializable{
    private String name;
    private int age;
    private transient double height;

    public Human(String name, int age, double height ){
        this.name = name;
        this.age = age;
        this.height = height;
    }
    public String getName(){
        return name;
    }
    public int getAge(){
        return age;
    }
    public double getHeight(){
        return height;
    }
}


実行結果

太郎
25
0.0


25行目~44行目でHumanクラスを定義しSerializableインターフェースを実装することで、オブジェクト単位で読み書きができるようにしています。


11行目でHumanクラスのtaroオブジェクトを生成します。

13行目~14行目でObjectInputSteamクラスとObjectOutputStreamクラスのオブジェクトを生成します。

15行目でwriteObject()を使用しtaroオブジェクトを出力ストリームに出力します。

16行目ではreadObject()で読み込んだオブジェクトをHumanクラスにキャストして変数readtaroに格納しています。

17行目~19行目でreadtaroオブジェクトからそれぞれのフィールドのゲッターメソッドを使って値を取り出しコンソール画面に出力をしています。

この時、Humanクラスのheightフィールドはtransient指定されているためシリアライズの対象とならず、データの読み書きをしていないので、出力結果が0.0となっていることがわかります。

20行目~22行目のcatchブロックはマルチcatch構文を使用しています。

21行目のprintStackTrace()を使用すると例外発生原因のクラス名、メソッド名、行番号、ファイル名といった情報が格納されているスタックから情報を取り出すことができます。


まとめ

  • Fileクラス

    • java.io.Fileクラスはディスクに保存されているファイルやディレクトリをオブジェクトとして表現します。
    • Fileクラスのメソッドを使用すると、ファイルやディレクトリが存在するかどうか確認したり、ファイルかディレクトリかを判断したり、ディレクトリに存在しているもののリストを取得したりします。
  • テキストファイルとバイナリファイル

    • コンピュータの中では、様々な数字や文字などは一定の個数の0と1の並びで表現します(2進数表現)。
    • テキストファイルとは、文字として解釈可能なデータです。
    • バイナリファイルとは、0と1の2進数で表現されており、人間が直接読んだり、編集することはできません。
    • テキストファイルの読み書きには、java.io.FileWriterクラスとjava.io.FileReaderクラスを使用します。
    • バイナリファイルを読み書きするには、java.io.FileOutPutStreamクラスとjava.io.FileInputStreamクラスを使用します。
  • ストリーム

    • ストリームとはプログラムとファイルとの間のデータの流れのことです。
    • 入力ストリームと出力ストリームがあります。
    • キャラクタストリームでは、データの読み書きを16ビット(2バイト)単位で行い、バイトストリームでは8ビット(1バイト)単位で読み書きを行います。
    • Javaは1文字をUnicodeで16ビットデータとして扱っています。
    • キャラクタストリームを使用すると、キャラクター単位で読み書きをするので、OSの文字コードを意識せず入出力をすることができます。
  • テキストファイルの読み書き

    • FileReaderクラスとFileWriterクラスはデータの読み書きを、16ビット(文字)単位で行います。
    • read()メソッドは、入力ストリームから1文字(1バイト)ずつを読み込み、ファイルの終わりに達すると-1を返します。
    • read()メソッドでは、読み込まれる際にchar型ではなくint型で返されるので、read()メソッドの戻り値が-1でない場合は、char型にキャストして文字情報を取得するようにします。
    • flush()はバッファにたまっているデータを出力先にただちに書き込みます。
  • バイナリファイルの読み書き

    • FileInputStreamクラスとFileOutputStreamクラスを使用するとバイナリファイルを読み書きできます。
    • 文字列をバイトデータ(2進数)に変換する、getBytes()メソッドを使用します。
  • 基本データ型とString型のデータの読み書き

    • DataInputStreamクラスとDataOutStreamクラスを使用すると、int型などの基本データ型およびString型のデータを読み書きすることができます。
  • 文字列のブロック単位での読み書き

    • BufferedReaderクラスとBufferedWriterクラスは1文字ずつ入出力するのではなく、バッファに文字列をためていき、たまった文字列をまとめて読み込んだり、書き込んだりします。
    • readLine()を使用すると、行単位で読み込むことができ、行の終わりは改行コードなどで認識します。
  • シリアライズ

    • 直列化とも呼ばれ、入出力の際に、バイト単位や文字単位、行単位でなく、オブジェクト単位でファイルに書き込みます。
    • シリアライズされたオブジェクトを読み込んでメモリ上に復元することをデシリアライズ(直列化復元)といいます。
    • シリアライズしたいオブジェクトはSerializableインターフェースを実装します。
    • オブジェクトのシリアライズは、実際にはオブジェクトが保有するインスタンス変数がシリアライズの対象となります(static変数は対象外)。
    • 明示的にシリアライズの対象外としたい場合、transientキーワードをつけます。
  • オブジェクトの読み書き

    • ObjectInputStreamとObjectOutputStreamはオブジェクト単位でデータの入出力を行います。
    • オブジェクトの入出力を行うには、そのオブジェクトがシリアライズされている必要があります。


参考図書



独学で挫折しそうになったら、オンラインプログラミングスクール
未来エンジニア養成所Logo



あわせて学習したい

phoeducation.work phoeducation.work