generated at
Nimでバイナリファイルを読む
まえがき
Nimバイナリファイルを読む方法をまとめる

概要
streamsモジュールを使う
こんな感じで使う
a.nim
var strm = newFileStream("sample.dat", fmRead) echo strm.readStr(4) strm.close()
これだけだとわからんのでもう少し実践的なことかく

WAVファイルを読む
WAVは非圧縮の音声ファイル
データ構造が単純でパースしやすい
一部のデータを読み取ってファイル情報を調べてみる

上記の書式を踏まえてデータを取り出してみる
以下のようなファイルが存在する
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ファイル
xxdで16進データと文字を出力した
右側を見ると、ところどころに文字が存在することが分かる
これらを読み取ってみる
WAVファイルは最低3つのチャンクを持つ
最初のチャンクはRIFFChunkDescriptor
これは3つのデータをもつ
それぞれ抽出してみる
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
result.txt
id = RIFF size = 1359442 format = WAVE
read*** 系のプロシージャは実行してデータを取得すると同時にストリームの位置を移動する
なのでreadを実行するたびに異なる値が取得されている
位置を移動せずに値だけ取得するには peek*** 系のプロシージャを実行する
size はファイルサイズ全体から8byte引いた値になる
simple.wav のファイルサイズは 1359450 なので値も一致する
バイナリを読むときは基本こんな streams のプロシージャを使って read でデータ取得と移動をひたすら繰り返す感じで行う
streams の読み書き時のバイトデータについてはNimでバイトオーダ(エンディアン)を意識してデータ読み書きするを参照
こんな感じで地道にWAVファイルの書式とにらめっこしながらNimでWAVファイルのライブラリを書いた