これは「Ruby脳にはCrystalつらい Advent Calendar 2015」の21日目の記事です。
Crystal の String は UTF-8 固定なのでバイナリデータを String で扱うことはできません。
バイナリデータを扱うには String ではなく Slice を使います。
Slice(UInt8).new(1024)
とすると 1024バイトのメモリが獲得されます。C の calloc(sizeof(char), 1024)
みたいな感じですね。
Slice のインスタンスは配列と同じような感じで使えますが、長さは固定で拡張したり縮小したりはできません。
slice = Slice(UInt8).new(5) slice[0] = 11u8 slice[1] = 22u8 slice[2] = 33u8 slice #=> [11, 22, 33, 0, 0]
File や Socket 等の IO からバイナリデータを読み込むには IO#read
を使います。
File.open("/etc/hosts") do |f| buf = Slice(UInt8).new(1024) length = f.read(buf) buf[0, length] end
読み込むためのバッファを用意して、IO#read
の戻り値で読み込んだバイト数を調べて…というような感じでやるしかないようです。
まるで C みたいで、ちょっとつらい。