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