1.読者対象
- Java初心者。「クラス」とか「インタフェースを実装」とか言われてもわかる人。型には基本型とクラス型があると知っている人。ストリームはあやふやでもいい。(この記事で解説します)
- Java8未満を使っているが8以降に切り替えることを検討中の人。
2.前提知識のおさらいとよくある誤解の解消
2-1.Serialize(シリアライズ) とは
インスタンスのデータをファイルに書き出すこと。
2-2.クラスにimplements Serializable
って書けばいいんだよね
書く必要はあるが、書けばよいわけではない。
Serializableインタフェースを実装することは「serializeしたいよ」ではなく「serializeしてもいいよ」という宣言。
したがって要件をクリアする必要がある。
要件は参考サイト[1]によれば、フィールドがすべて基本型またはシリアライズ可能なクラス型であることである。
ちなみにStringはシリアライズ可能である。
2-3.シリアライズのやり方を簡潔に説明して
1.基本型あるいはシリアライズ可能なクラス型のみのフィールドから成るクラスAを作り、
implements Serializable
する。
2.oos.writeObject(Aのインスタンス);
実行。
oos は ObjectOutputStream
型のインスタンスで、インスタンス生成時に保存先のファイル名を指定している。
3.好きなところでois.readObject()
する。
ois は ObjectInputStream
型のインスタンスで、インスタンス生成時に読み込み元のファイル名を指定している。
2-4.ストリームがよくわからん
そもそもJavaには「全く別なストリーム」が2種類存在する。
配列が「フィールドだけのクラス」なら
ストリームは「メソッドだけのクラス」
(独自解釈)
Stream<T>
は java.util.stream
パッケージにあるストリーム。
(hoge)?InputStream
や
(huga)?OutputStream
とかは
java.io
パッケージにあるストリーム。
新しいのは前者。
中間操作とか終端操作とかセミコロンレスとかいうのも前者
2-4-1.新しいStream<T>を簡単に説明して
ストリームを日本語にすると川だから、「データのが川の水みたいに流れてる」とよくいわれる。
「ピタゴラスイッチ」と比較するとわかりやすいというのが僕の感想。
(共通点)
川やピタゴラスイッチ | |
---|---|
巻き戻し | できない |
やること | 水などを順番に処理 |
(相違点)
川 | ピタゴラスイッチ | |
---|---|---|
処理の対象 | 川から水を採る。加えはしない。水であることは不変 | 変化を楽しむ。ボール→ラジコン→ドミノ・・・ |
副作用 | 限定的 | さまざま |
新しいストリームStream<T>は
可読性は高いが、書くには勉強が必要
- メソッド参照(コンストラクタ参照)
- ラムダ式
Double[] array = {5, 6.7, 9.1, 6};
Stream<Double> stream = Stream.of(array).//生成
filter(d->(int)d==d).//中間操作
toArray(i->new Integer[i]);//終端操作
//{5,6}
2-4-2.古いストリームI/Ostreamを簡単に説明して
InputStreamやOutputStreamは古いほうのストリーム。
以下I/Ostreamと略して説明。
2-4-2.古いストリームI/Ostreamを簡単に説明して
イメージ的には「外の世界とバイト配列をやり取りする」もの。
バイト単位だから、データの入出力ならなんでもできる[2]!
例1:標準入力new Scanner(System.in);
→ System.in
が外の世界(キーボード)とつながるInputStream
例2:標準出力System.out.println();
→ System.out
が外の世界(モニタ)とつながるOutputStream
//例3:ファイル入出力[3] ①utf8.txtを読み込む
BufferedReader br =
new BufferedReader(//「バッファ※1」付きReader※2
new InputStreamReader(//InputStream→Reader
new FileInputStream(//File→InputStream
new File("utf8.txt"))
,"UTF-8"));//InputStreamReaderの第2引数
//(続く)
//(続き) ②sjis.txtへ書き込み準備
BufferedWriter bw =
new BufferedWriter(//バッファ付きWriter
new OutputStreamWriter(//OutputStream→Writer
new FileOutputStream(//File→OutputStream
new File("sjis.txt"))
,"Shift-JIS"));
//(続く)
//(続き)
String data;
while((data=br.readLine()) != null)//行が続く限り1行ずつ読む
{//dataにはutf8.txt 1行分の文字列(改行コード含まず)が入っている
byte[] b = data.getByte("UTF-8");//UTF-8としてバイト列へ変換
bw.write(new String(b, "Shift_JIS"));
//バイト列をShift_JISで文字列に変換してsjis.txtへ書き込む
bw.newLine();//改行コードの書き込み
}bw.close();br.close();//ファイルを閉じる
※1バッファとは
1バイトずつ(Reader/Writerなら1文字ずつ)読み込むと効率が悪い
(たこ焼きを1つずつ焼くようなもの)
そこで、一定数貯めて、まとめて読み込む
(たこ焼き器は同時に複数個焼ける)
※2Readerとは
文字を読めるようにしたInputStream
文字コードを指定することで、「何バイト読めば1文字か」などがわかる。
次回予告
【java 8以降】serializeしたデータに簡単に署名とかを追加【Serialize】(2/3―(デ)?シリアライズしてみる)
- Serializableを最も素直に実装したクラスを作り、 ObjectI/Ostreamに触れる。
ここまでの参考サイト
[1]https://www.ne.jp/asahi/hishidama/home/tech/java/serial.html
[2]https://qiita.com/castaneai/items/3dbdd8543b020aa903cb
[3]https://www.sejuku.net/blog/20746
その他https://qiita.com/frost_star/items/fb87caf05e106c46dfe4