2010年02月17日

rubyでバイトオーダー(エンディアン)処理

rubyで、array.pack,unpackを使用してバイトオーダー(エンディアン)処理をします。

packテンプレート文字列

下記サンプルは、
 1.指定エンディアンのファイルを作成
 2.作成したファイルを読み込み、エンディアンに合った形で読み書きする
場合の例です。

◆バイトオーダー(エンディアン)を考慮したファイル読み書き

endian = "BE" #big endian. little endianしたい場合は"LE"を設定

##########ダミー用のファイル作成(big endian)##########
f = File.open("test.bin","wb")
case endian
when "BE" #big endian
f.write([0xAA].pack("n"))
f.write([0xCCDD].pack("N"))
when "LE" #little endian
f.write([0xAA].pack("v"))
f.write([0xCCDD].pack("V"))
end
f.close

##########読み取り##########
bin = File.open("test.bin","rb"){|f| f.read} #ファイル全部読み取る

#特異メソッド追加
class << bin
attr_accessor :short,:long
def read_s(pos)
self[pos..(pos+1)].unpack(@short)[0]
end
def read_l(pos)
self[pos..(pos+3)].unpack(@long)[0]
end
def write_s(pos,val)
self[pos..(pos+1)] = [val].pack(@short)
end
def write_l(pos,val)
self[pos..(pos+3)] = [val].pack(@long)
end
end

case endian
when "BE" #big endian
bin.short,bin.long = "n","N"
when "LE" #little endian
bin.short,bin.long = "v","V"
end

#0バイト目からshort(2byte)読み込む
p bin.read_s(0).to_s(16)
#2バイト目からlong(4byte)読み込む
p bin.read_l(2).to_s(16)

#書き換え
bin.write_s(0,0xBB)
bin.write_l(2,0xEEFF)

#0バイト目からshort(2byte)読み込む
p bin.read_s(0).to_s(16)
#2バイト目からlong(4byte)読み込む
p bin.read_l(2).to_s(16)


要点としては、読み込んだバイナリ配列に特異メソッドを追加して、エンディアン処理をラップする所です。

#特異メソッド追加
class << bin
attr_accessor :short,:long
def read_s(pos)
self[pos..(pos+1)].unpack(@short)[0]
end
def read_l(pos)
self[pos..(pos+3)].unpack(@long)[0]
end
def write_s(pos,val)
self[pos..(pos+1)] = [val].pack(@short)
end
def write_l(pos,val)
self[pos..(pos+3)] = [val].pack(@long)
end
end

case endian
when "BE" #big endian
bin.short,bin.long = "n","N"
when "LE" #little endian
bin.short,bin.long = "v","V"
end

short,long用の読み書き文字列テンプレート変数を作成

attr_accessor :short,:long

short,longのread,write

def read_s(pos)
self[pos..(pos+1)].unpack(@short)[0]
end
def read_l(pos)
self[pos..(pos+3)].unpack(@long)[0]
end
def write_s(pos,val)
self[pos..(pos+1)] = [val].pack(@short)
end
def write_l(pos,val)
self[pos..(pos+3)] = [val].pack(@long)
end

endianにより文字列テンプレートを設定

case endian
when "BE" #big endian
bin.short,bin.long = "n","N"
when "LE" #little endian
bin.short,bin.long = "v","V"
end



posted by purigen at 00:00| Comment(0) | TrackBack(0) | Ruby | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。