倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

Groovy JDK? It's GDK! (File 編5) データストリーム・オブジェクトストリーム

今回はデータストリームとオブジェクトストリームに関連するメソッド(目次)。 あんまり詳しくないんで、サラッと流しマース。

データストリーム

まずはデータストリームに関連するメソッド。 データストリームとは、Java のプリミティブ型のストリームって感じの認識でいいんじゃないでしょうかね。 このストリームの読み書きは java.io パッケージに定義されている DataInputStream / DataOutputStream を使用します。 これらのクラスには readLong() や writeDouble() のようなプリミティブ型の読み書きメソッドが定義されています。 使い方の詳細は JavaDoc 参照のこと。 GDK が File クラスに追加しているデータストリーム関連のメソッドは以下の通り:

メソッド 返り値 since
入出力オブジェクトの取得 newDataInputStream()
newDataOutputStream()
DataInputStream
DataOutputStream
1.5.0
読み込み withDataInputStream(Closure c) Object 1.5.2
書き出し withDataOutputStream(Closure c) Object 1.5.2

まぁ、InputStream / OutputStream や Reader / Writer と同じような感じですね。 使い方も同じです。 ではサンプルコード: 

def data = new File('data-source')

// DataOutputStream
data.withDataOutputStream{ dos ->
    for(i in 0..20) dos.writeLong(i)
}

// DataInputStream
data.withDataInputStream{ dis ->
    while(dis.available() > 0){    // いつも上手くいくとは限らないかも。
        println dis.readLong()
    }
}

標準出力には0から20までの数字が書き出されます。 また、「data-source」ファイルにも内容が書き込まれますが、数字がそのまま書き出されるわけではないので、普通のテキストファイルなどで開いても読めません。

DataInputStream によってデータを読み込む際に DataInputStream#available() メソッドを用いていますが、このメソッドは「ブロックせずに読み込むバイト数を返す」メソッドなので、いつも上手くいくとは限りません。 ちょっと使ってみただけ。

オブジェクトストリーム

次はオブジェクトストリームに関連するメソッド。 オブジェクトストリームは、データストリームに加えてオブジェクトや配列、文字列なども読み書きできるようにしたストリームです。 java.io.Serializable を実装したオブジェクトを読み書きするやつです。 読み書きに使用するクラスは java.io パッケージの ObjectInputStream / ObjectOutputStream です。 GDK が File クラスに追加しているオブジェクトストリーム関連のメソッドは以下の通り:

メソッド 返り値 since
入出力オブジェクトの取得 newObjectInputStream()
newObjectInputStream(ClassLoader cl)
newObjectOutputStream()
ObjectInputStream
ObjectInputStream
ObjectOutputStream
1.5.0
読み込み withObjectInputStream(Closure c)
withObjectInputStream(ClassLoader cl, Closure c)
eachObject(Closure c)
Object
Object
void
1.5.2
1.5.2
1.0
書き出し withObjectOutputStream(Closure c) Object 1.5.0

だいたいデータストリームの場合と同じですが、ClassLoader を指定できる withObjectInputStream() メソッドと、オブジェクトを反復読み込みする eachObject() メソッドもあります。 ではサンプルコード:

def obj = new File('object-source')

// ObjectOutputStream
obj.withObjectOutputStream{ oos ->
    for(o in ['abc', 'def', 'ghi', 'jkl', 'mno'])
        oos.writeObject(o)
}

// ObjectInputStream
obj.withObjectInputStream{ ois ->
    5.times{
        println ois.readObject()
    }
}
println()

// eachObject() でオブジェクトを読み込んで列挙
obj.eachObject{
    println it
}

オブジェクトストリームからオブジェクトを読み込む場合は、eachObject() メソッドを使うのが簡単そう。 Serializable を実装した独自クラスの読み書きとかできるはずなんですが・・・

まぁ、次回は残ってるメソッドをまとめてやっつけちゃう予定。
プログラミングGROOVY Groovyイン・アクション Effective Java 第2版 (The Java Series)