バイトオーダーを選んでunpack

簡単なデータ変換を行うスクリプトをRubyで書いていた。

なんでRubyかというと、他の目的でRubyを使っている環境だったから。

処理を書いている中で、そういえばエンディアンを指定して整数とバイト列を往来するにはどうすればよいのだろうと。


Rubyではバイナリデータも文字列として扱うようですね。

Rubyでは文字列にエンコーディング情報が付加されているのだが、

ASCII-8BITってのがバイナリデータを扱うエンコーディングだと。

文字列を数字の配列に変換するためにはunpackメソッドを使うそう。

それでサンプルコードを見るとこんなことが書かれていた。

int_le = bytedata.byteslice(idx,4).unpack("L<")[0]
int_be = bytedata.byteslice(idx,4).unpack("L>")[0]

そもそもpack, unpackというのが慣れないところはあるが、

“<“という記号は一体何を表しているのかと気になった。


pack, unpackってのはPerlに由来しているのかな?

$text = pack("C*",@byte);
@byte = unpack("C*",$text);

のような感じで文字列$textと1byte単位の配列@byteを変換するのが典型的な使い方。

それぞれ引数の”C”がunsigned charに対応するというわけである。

ここには2byte以上の型もあり、32bit符号無し整数に対応するのが”L”である。

ただ、この”L”はバイトオーダーが環境依存である。(多くの場合はリトルエンディアンと考えられているが)

そこで “<“を付加するとリトルエンディアン、”>”を付加するとビックエンディアンと指定できる仕組みがあると。


こういうのってPerlにもあるのかと調べたらあるらしい。

もっともPerlでもRubyでもそうなのだが、ビックエンディアンの32bit符号無し整数は “N” でも表現できるそう。

なぜ “N”なのかというとネットワークバイトオーダーという意味らしい。

こちらの方がPerlでは一般的な書き方のようである。

逆にリトルエンディアンの32bit整数は “V” と書くそう。


このあたりは環境によりいろいろあるという話だが。

ただ、ちょっと前に.NET Frameworkのこの手の処理の実装例を見て驚いたんだけど……

BitConverter Class (Microsoft Learn)

この中でビッグエンディアンに対応させるためにはどうするかという話で、

IsLittleEndianがtrueならば、Array.Reverseでバイト列の順番を反転する処理を入れるとなっている。

果たして.NET Frameworkが動く環境でビックエンディアンがあるのかは疑問なのだが、

これを見て、実行環境のバイトオーダーと不一致ならばバイト順を反転させることで対応してくれということらしい。

もうちょっとなんとかならんのかと思うが。