💨

Node.jsでもBinaryを読み出したい!

2022/03/19に公開

Why?

落とし戸関数や乱数生成機を作る時などBit Shiftを基数変換せずに扱うときに処理が想定通りに行われてるのかの確認や、バイナリを埋め込むと扱いやすさが変わってくるので作った。ググり不足で本当にこの実装してるユーティリティないのか?と思ったので一応間に合わせで作った実装を公開することであわよくば有識者の方に助けてもらおうという魂胆である。

Buffer

単にByteコードを読み出したいたけならBufferクラスを利用すれば1byteごとに呼び出せる。

export function* byteReadGenerater(buffer/* : Buffer */) {
    for (let i = 0, len = buffer.length; i < len; i++) {
        yield buffer.readUint8(i)
    }
}

Binaryを読み出すには?

一気にBufferの中身を読み出すとファイルと同じだけのbinaryの文字列が生成されてしまい大変よろしくないので、generatorでメモリを解放しながら読み込んでいく。

export function* binaryReadGenerater(buffer/* : Buffer */) {
    let g = byteReadGenerater(buffer)
    for(let byte of g) {
        const binaryStr = byte.toString(2)
        for(let i = 0, len = binaryStr.length; i < len; i++){
            yield Number(binaryStr[i])
        }
    }
}

一応こんな感じで動くコードが用意できる。Number型の変数は.toString(2)で二進数表示で文字列型にできるらしい。ただし、1byteずつ読むとはいえtoStringに変換するのは中々イケてない。普通に格納している数字を10進数で読む前にメモリにはバイナリで存在していてBufferで読み出せているのだからnode.jsでバイナリのまま読み出せる標準実装されててもいい気がしている。本当にないんでしょうか?

もっといい方法あるよという方いらっしゃったら教えてください。

上記のコードは上位bitにおいて0連続する桁数を省略してしまうのでうまくいかない。

追記

toString(2)では、1 byteの上位bitが連続で0になっているものを省略してしまうので、読み出し型を論理積を使う方法に修正した。おそらくnode.jsのbuiltin libraryを拡張する手段を取らない限りこれ以上工夫をするのは難しそう。

export function* binaryReadGenerator(buffer: Buffer): Generator<0 | 1, void> {
    let g = byteReadGenerator(buffer)
    for (let byte of g) {
        for(let shift = 7; shift >= 0; shift--){
            let nextValue: 0 | 1 = (byte & (1 << shift)) > 0 ? 1: 0
            yield nextValue
        }
    }
}

Discussion