Nimでバイナリファイルを読む
まえがき
概要
こんな感じで使う
code:a.nim
var strm = newFileStream("sample.dat", fmRead)
echo strm.readStr(4)
strm.close()
これだけだとわからんのでもう少し実践的なことかく
データ構造が単純でパースしやすい
一部のデータを読み取ってファイル情報を調べてみる
上記の書式を踏まえてデータを取り出してみる
以下のようなファイルが存在する
code:a.sh
$ xxd simple.wav | head
00000000: 5249 4646 52be 1400 5741 5645 666d 7420 RIFFR...WAVEfmt
00000010: 1000 0000 0100 0200 44ac 0000 9809 0400 ........D.......
00000020: 0600 1800 4c49 5354 2600 0000 494e 464f ....LIST&...INFO
00000030: 4953 4654 1a00 0000 4c4d 4d53 2028 6c69 ISFT....LMMS (li
00000040: 6273 6e64 6669 6c65 2d31 2e30 2e32 3829 bsndfile-1.0.28)
00000050: 0000 6461 7461 00be 1400 0200 0002 0000 ..data..........
00000060: 47c1 0247 c102 eb81 05eb 8105 4641 0846 G..G........FA.F
00000070: 4108 b9fe 0ab9 fe0a 9eb9 0d9e b90d 5871 A.............Xq
00000080: 1058 7110 4025 1340 2513 bdd4 15bd d415 .Xq.@%.@%.......
00000090: 2f7f 182f 7f18 fd23 1bfd 231b 88c2 1d88 /../...#..#.....
これはlmmsという音楽作成ソフトで作成した簡単なWAVファイル 右側を見ると、ところどころに文字が存在することが分かる
これらを読み取ってみる
WAVファイルは最低3つのチャンクを持つ
これは3つのデータをもつ
それぞれ抽出してみる
code:r1.nim
import streams
var strm = newFileStream("simple.wav", fmRead)
let id = strm.readStr(4)
let size = strm.readUint32()
let format = strm.readStr(4)
strm.close()
echo "id = " & id
echo "size = " & $size
echo "format = " & format
code:result.txt
id = RIFF
size = 1359442
format = WAVE
read***系のプロシージャは実行してデータを取得すると同時にストリームの位置を移動する
なのでreadを実行するたびに異なる値が取得されている
位置を移動せずに値だけ取得するにはpeek***系のプロシージャを実行する
sizeはファイルサイズ全体から8byte引いた値になる
simple.wavのファイルサイズは1359450なので値も一致する
バイナリを読むときは基本こんなstreamsのプロシージャを使ってreadでデータ取得と移動をひたすら繰り返す感じで行う