バイナリファイルの読み込みメモ

pmdローダーを作る前に。

import java.io.File;
import java.io.FileInputStream;
import java.nio.ByteBuffer;

// 全部読み込む
File f=new File(path);
int length=(int)f.length();
byte[] buf=new byte[length];
FileInputStream fs=new FileInputStream(path);
fs.read(buf);
fs.close();

// nio.ByteBuffer化する
ByteBuffer bb=ByteBuffer.wrap(buf);

// ByteBufferから任意の型の値を取り出して、現在位置を進める

// float
bb.getFloat();

// byte(2^8)
bb.get()

// WORD(2^16)
(bb.get()<<8)+bb.get()

// DWORD(2^32)
(bb.get()<<24)+(bb.get()<<16)+(bb.get()<<8)+bb.get()

// String(length)
new String(buf, bb.position(), length, Charset.forName("MS932"));
bb.position(bb.position()+lenght);

こんだけできれば十分かな。
あとはごりごり書けばよし。

微妙に間違っていた

Javaはunsignedが無いので修正。
Javaのbyte型ってCのunsigned charかと思ったら、signed char型なのね。
Javaのchar型は敢えて言えば、Cのwchar_tになるか(utf16格納用なので)。
wchar_tだと実装系依存になりそうだから2byteの整数型であるところの
unsinged shortが対応するか。
あと、endian的な問題に対処してscala的には下記のようになった。


さらにendianでもう一手必要だったのを追記。

class ByteReader(val path :File){
    val CP932=Charset.forName("MS932")

    val buf=new Array[Byte](path.length.asInstanceOf[Int])
    val io=new FileInputStream(path)
    io.read(buf)
    io.close()

    // 追記。getFloatに必要だった
    val bb=ByteBuffer.wrap(buf).order(ByteOrder.LITTLE_ENDIAN)

    def pos :Int=bb.position
    def isEnd :Boolean=bb.position>=bb.capacity

    def getString(length :Int) :String={
        val ret=new String(buf, bb.position, length, CP932)
        bb.position(bb.position()+length)
        ret
    }
    def get() :Int={
        val b=bb.get()
        if(b>=0) b else b+256
    }
    def getWORD() :Int={
        val b0=get()
        val b1=get()
        (b1<<8) + b0
    }
    def getDWORD() :Int={
        val b0=get()
        val b1=get()
        val b2=get()
        val b3=get()
        (b3<<24) + (b2<<16) + (b1<<8) + b0
    }
    def getFloat() :Float=bb.getFloat()
    def getVector2() :Vector2=Vector2(getFloat(), getFloat())
    def getVector3() :Vector3=Vector3(getFloat(), getFloat(), getFloat())
    def getRGB() :RGB=RGB(getFloat(), getFloat(), getFloat())
    def getRGBA() :RGBA=RGBA(getFloat(), getFloat(), getFloat(), getFloat())
}