java.nio.ByteBuffer
ByteBuffer は便利
DataInputStream の readFully みたいに指定サイズを
Byte バッファに読み込んで ByteBuffer にして返すメソッド。
この時のデータはリトルエンディアン
import java.nio.{ByteBuffer,ByteOrder} ..snip.. def read[S <: { def read(b: Array[Byte], n: Int, len: Int): Int }](in: S) (size: Int): ByteBuffer = { val b = new Array[Byte](size) val bbuf = ByteBuffer.wrap(b) bbuf.order(ByteOrder.LITTLE_ENDIAN) var num = 0 while (num < size) { val cnt = in.read(b, num, size - num) if (cnt < 0) throw new EOFException() num += cnt } bbuf } ..snip..
読みだしたデータを ByteBuffer にして扱うと
Int, Short, Double, 文字列 等の各種の型でデータを取り出して処理する際に便利。
..snip.. val bbuf = read[InputStream](in)(32) println(" Int data : %d".format(bbuf.getInt(0))) val sdat: Int = bbuf.getShort(4) println(" Short data: %d".format(sdat)) println(" Double data : %.10f".format(bbuf.getDouble(16))) ..snip..
ファイル保存した文字列を表示するときのエンコーディング指定
いまさらだがファイル保存した文字列のエンコーディング指定でハマった。
Shift_JIS でバイナリファイルに保存した文字列を読みだして
ローカルのエンコーディング(この時は EUC-JP)で表示する時のやり方
def getStr(bb: ByteBuffer, pos: Int, size: Int): Pair[String,String] = { val enc = System.getProperty("file.encoding") val buf = new Array[Byte](size) for (i <- 0 until size) buf(i) = bb.get(pos + i) val hex = for (i <- 0 until size) yield { "%02X".format(buf(i)) } (hex.mkString, new String(new String(buf, "SJIS").getBytes(enc), enc)) }
読みだしたデータを ByteBuffer で渡して表示エンコーディング文字列と
その文字列の16進数ダンプを返すメソッド。
データの ByteBuffer とその読み出し位置(pos)、読み出しサイズ(size)を
引数に指定して、読みだした文字列(表示エンコーディング)とその文字列
の16進数ダンプの文字列の Pair を返す。
..snip.. val (hex, str) = getStr(bbuf, 32, 16) println(" str: %s".format(str)) println(" hex: %s".format(hex) ..snip..