generated at
Nimでバイトオーダ(エンディアン)を意識してデータ読み書きする
概要
Nimでstreamsモジュールを使ってのデータ読み書きについてまとめる
バイトオーダ(エンディアン)を意識する必要がある
WAVだとリトルエンディアンで数値データが格納されている
SMFだとビッグエンディアンで数値が格納されている
Nimでエンディアンを扱うにはendiansモジュールを使う
Nimのstream読み書きを調べてみた

streamsの読み書きのエンディアンを調べる
streamsモジュールには何のエンディアンでデータを読み書きするのか説明がない
調べた

数値の読み書きのエンディアン
Nimでは数値型についてはリトルエンディアンで読み書きを行う
little.nim
import streams block: var strm = newFileStream("9.dat", fmWrite) strm.write(9'u32) strm.close() block: var strm = newFileStream("9.dat", fmRead) echo strm.readUint32() strm.close()
このコードを実行した結果生成される 9.dat のバイナリを調べると以下のようになる
9.sh
$ xxd 9.dat 00000000: 0900 0000 ....
一番下位のバイトが先頭に来ている
そして readUint32 で取得した値を出力すると 9 が出力される
よって readUint32 リトルエンディアンとしてデータを読み込んでいる

文字列の読み書きのエンディアン
Nim string 型においてはビッグエンディアンで読み書きを行う
str.nim
import streams block: var strm = newFileStream("hello.dat", fmWrite) strm.write("hello") strm.close() block: var strm = newFileStream("hello.dat", fmRead) echo strm.readStr(5) strm.close()
このコードを実行した結果生成される hello.dat のバイナリを調べると以下のようになる
9.sh
$ xxd hello.dat 00000000: 6865 6c6c 6f hello
helloがhelloの順序のまま格納されている
そして readStr で取得した値を出力すると hello が出力される
よってreadStrはビッグエンディアンとして読み込む

数値をビッグエンディアンで読み取る
数値型はリトルエンディアンで読み取ることが分かった
数値型をビッグエンディアンで読み取るにはendiansモジュールを使う
以下のコードは、リトルエンディアンとして読み取ったデータをビッグエンディアンに直す
big.nim
import streams, endians block: var strm = newFileStream("big.dat", fmWrite) strm.write(0'u8) strm.write(0'u8) strm.write(0'u8) strm.write(9'u8) strm.close() block: var strm = newFileStream("big.dat", fmRead) var src = strm.readUint32() echo "littleEndian32: " & $src var dst: uint32 bigEndian32(addr(dst), addr(src)) echo "bigEndian32: " & $dst strm.close()
result.txt
littleEndian32: 150994944 bigEndian32: 9
ビッグエンディアンで書き込んだデータを readUint32 で読み取ると当然 9 にならない
endians で数値をビッグエンディアンに直す