Rubyでのビッグエンディアンとリトルエンディアンの相互変換
結構プログラムやってきましたけどあんまり意識してませんでしたね。
このビッグエンディアンとリトルエンディアン
バイナリファイルを扱うと意識しないとだめなようで、ちょっと嫌なんですけど調べた
ビッグエンディアンとリトルエンディアンってなんだ?
コンピュータは1バイト(8ビット)ずつ情報を扱いたいようなんだが、中には2バイトを超えるデータもある。32bitのコンピュータならint型も32bitだからint型を格納するなら4バイトいるってことになりますね
4バイト・・・1バイト超えてますね。
ここでこのデータを扱うときに4バイトの箱を用意して、データを1バイトずつにブツ切りにして、箱の頭から順番に詰めるのがリトルエンディアン、箱のケツから詰めるのがビッグ
こうなるとリトルでは上位ビットが先に下位ビットが後に配置されますね、ビッグは逆で下位が先で、上位が後に配置されます・・・・
簡単に言うなら並びが逆なんですわ、単にそんだけで、伝統的にそういう決まりなだけで深い意味は内容なんですけど、ホント迷惑だわ
その意味をそのまま捉えて組んだ初期プログラム
puyopuyo = open("./hoge") puyopuyo.binmode hoge1 = puyopuyo.read(1) hoge2 = puyopuyo.read(1) hoge3 = puyopuyo.read(1) hoge4 = puyopuyo.read(1) popopo = (hoge4 + hoge3 + hoge2 + hoge1)
すばらしいですね。1バイトずつ読んで逆順にして結合。わかり易過ぎw
実際これで合ってるようなんですけど
もっとうまい手がPerlのソースにあったのでパクリました
エンディアン非依存の変換を利用した変換
バイト列のデータから数値や文字オブジェクトに直すときに使うメソッドがあります
- String.unpack
- Array.pack
この2つ
unpackでオブジェクトに、packでバイト列に直します。このunpack,packには引数を与えることによってどう解釈するか変えれると
このパターンの中に処理系のエンディアンに依存しない「32ビットビッグエンディアン数値変換」と「32ビットリトルエンディアン数値変換がある
つまり
ビッグバイト列→【ビッグ解釈変換】→数値→【リトル解釈変換】→リトルバイト列
とやってやろうと
え・・・さっさとソースをかけと
byteData = byteData.unpack(N*) byteData = byteData.pack(V*)
これで完成です。
とういうことです。
こうすると最終的なものはリトルエンディアンなので、リトルエンディアン処理系で煮たり焼いたりできるようにうなります
ってか直に変換できるメソッド使えって? そんなのねーんだよw
↓完全版コード
io = File.open("hoge" , "r") #4バイト読む byteData = io.read(4) byteData = byteData.unpack(N*) byteData = byteData.pack(V*) numHoge = byteData.unpack(i*) p numHoge
↓更新は↓中心に行いますので、↑の情報で満足できなかった場合は覗いてみてください
http://yakinikunotare.boo.jp/orebase/index.php?Ruby%2F%A5%D0%A5%A4%A5%CA%A5%EA%A5%D5%A5%A1%A5%A4%A5%EB%A4%CE%A5%D3%A5%C3%A5%B0%A5%A8%A5%F3%A5%C7%A5%A3%A5%A2%A5%F3%A4%C8%A5%EA%A5%C8%A5%EB%A5%A8%A5%F3%A5%C7%A5%A3%A5%A2%A5%F3%A4%CE%CA%D1%B4%B9