以下にあげるものは、Array#pack、String#unpack のテンプレート文字の一覧です。テンプレート文字は後に「長さ」を表す数字 を続けることができます。「長さ」の代わりに`*'とすることで「残り全て」 を表すこともできます。
長さの意味はテンプレート文字により異なりますが大抵、
"iiii"
のように連続するテンプレート文字は
"i4"
と書き換えることができます。
下記の説明の中で short や long はシステムによらずそれぞれ 2, 4バイトサ イズの数値(32ビットマシンで一般的なshort, longのサイズ)を意味していま す。`s', `S', `l', `L' に対しては直後に `_'または`!'を("s!"のように) 続けることでシステム依存のshort, long のサイズにすることもできます。 *1
`i', `I' (int)のサイズは常にシステム依存であり、`n', `N', `v', `V' のサイズは常にシステム依存ではない(`!'をつけられない)ことに注意してください。
テンプレート文字列中の空白類は無視されます。 ruby 1.7 feature: また、`#' から改行あるいはテンプレート文字列の最後まではコメントとみな され無視されます。
説明中、Array#packとString#unpackで違いのあるものは/で区切って 「Array#packの説明/String#unpackの説明」としています。
a
ASCII文字列(null文字を詰める/後続するnull文字やスペースを残す)
["abc"].pack("a") => "a" ["abc"].pack("a*") => "abc" ["abc"].pack("a4") => "abc\0" "abc\0".unpack("a4") => ["abc\0"] "abc ".unpack("a4") => ["abc "]
A
ASCII文字列(スペースを詰める/後続するnull文字やスペースを削除)
["abc"].pack("A") => "a" ["abc"].pack("A*") => "abc" ["abc"].pack("A4") => "abc " "abc ".unpack("A4") => ["abc"] "abc\0".unpack("A4") => ["abc"]
Z
null終端文字列(a
と同じ / 後続するnull文字を削除)
["abc"].pack("Z") => "a" ["abc"].pack("Z*") => "abc" ["abc"].pack("Z4") => "abc\0" "abc\0".unpack("Z4") => ["abc"] "abc ".unpack("Z4") => ["abc "]
b
ビットストリング(下位ビットから上位ビット)
"\001\002".unpack("b*") => ["1000000001000000"] "\001\002".unpack("b3") => ["100"] ["1000000001000000"].pack("b*") => "\001\002"
B
ビットストリング(上位ビットから下位ビット)
"\001\002".unpack("B*") => ["0000000100000010"] "\001\002".unpack("B9") => ["000000010"] ["0000000100000010"].pack("B*") => "\001\002"
h
16進文字列(下位ニブルが先)
"\x01\xfe".unpack("h*") => ["10ef"] "\x01\xfe".unpack("h3") => ["10e"] ["10ef"].pack("h*") => "\001\376"
H
16進文字列(上位ニブルが先)
"\x01\xfe".unpack("H*") => ["01fe"] "\x01\xfe".unpack("H3") => ["01f"] ["01fe"].pack("H*") => "\001\376" ["7e"].pack("H2") => "~"
c
char (8bit 符号つき整数)
"\001\376".unpack("c*") => [1, -2] [1, -2].pack("c*") => "\001\376" [1, 254].pack("c*") => "\001\376"
C
unsigned char (8bit 符号なし整数)
"\001\376".unpack("C*") => [1, 254] [1, -2].pack("C*") => "\001\376" [1, 254].pack("C*") => "\001\376"
s
short (16bit 符号つき整数, エンディアンに依存) (s! は 16bit でなく、short のサイズに依存)
リトルエンディアン:
"\001\002\376\375".unpack("s*") => [513, -514] [513, 65022].pack("s*") => "\001\002\376\375" [513, -514].pack("s*") => "\001\002\376\375"
ビッグエンディアン:
"\001\002\376\375".unpack("s*") => [258, -259] [258, 65277].pack("s*") => "\001\002\376\375" [258, -259].pack("s*") => "\001\002\376\375"
S
unsigned short (16bit 符号なし整数, エンディアンに依存) (S! は 16bit でなく、short のサイズに依存)
リトルエンディアン:
"\001\002\376\375".unpack("S*") => [513, 65022] [513, 65022].pack("s*") => "\001\002\376\375" [513, -514].pack("s*") => "\001\002\376\375"
ビッグエンディアン:
"\001\002\376\375".unpack("S*") => [258, 65277] [258, 65277].pack("S*") => "\001\002\376\375" [258, -259].pack("S*") => "\001\002\376\375"
i
int (符号つき整数, エンディアンと int のサイズに依存)
リトルエンディアン, 32bit int:
"\001\002\003\004\377\376\375\374".unpack("i*") => [67305985, -50462977] [67305985, 4244504319].pack("i*") => RangeError [67305985, -50462977].pack("i*") => "\001\002\003\004\377\376\375\374"
ビッグエンディアン, 32bit int:
"\001\002\003\004\377\376\375\374".unpack("i*") => [16909060, -66052] [16909060, 4294901244].pack("i*") => RangeError [16909060, -66052].pack("i*") => "\001\002\003\004\377\376\375\374"
I
unsigned int (符号なし整数, エンディアンと int のサイズに依存)
リトルエンディアン, 32bit int:
"\001\002\003\004\377\376\375\374".unpack("I*") => [67305985, 4244504319] [67305985, 4244504319].pack("I*") => "\001\002\003\004\377\376\375\374" [67305985, -50462977].pack("I*") => "\001\002\003\004\377\376\375\374"
ビッグエンディアン, 32bit int:
"\001\002\003\004\377\376\375\374".unpack("I*") => [16909060, 4294901244] [16909060, 4294901244].pack("I*") => "\001\002\003\004\377\376\375\374" [16909060, -66052].pack("I*") => "\001\002\003\004\377\376\375\374"
l
long (32bit 符号つき整数, エンディアンに依存) (l! は 32bit でなく、long のサイズに依存)
リトルエンディアン, 32bit long:
"\001\002\003\004\377\376\375\374".unpack("l*") => [67305985, -50462977] [67305985, 4244504319].pack("l*") => RangeError [67305985, -50462977].pack("l*") => "\001\002\003\004\377\376\375\374"
L
unsigned long (32bit 符号なし整数, エンディアンに依存) (L! は 32bit でなく、long のサイズに依存)
リトルエンディアン, 32bit long:
"\001\002\003\004\377\376\375\374".unpack("L*") => [67305985, 4244504319] [67305985, 4244504319].pack("L*") => "\001\002\003\004\377\376\375\374" [67305985, -50462977].pack("L*") => "\001\002\003\004\377\376\375\374"
q
ruby 1.7 feature: long long (符号付き整数, エンディアンと long long のサイズに依存) (C で long long が扱えない場合には 64bit)
リトルエンディアン, 64bit long long:
"\001\002\003\004\005\006\007\010\377\376\375\374\373\372\371\370".unpack("q*") => [578437695752307201, -506097522914230529] [578437695752307201, -506097522914230529].pack("q*") => "\001\002\003\004\005\006\a\010\377\376\375\374\373\372\371\370" [578437695752307201, 17940646550795321087].pack("q*") => "\001\002\003\004\005\006\a\010\377\376\375\374\373\372\371\370"
Q
ruby 1.7 feature: unsigned long long (符号なし整数, エンディアンと long long のサイズに依存) (C で long long が扱えない場合には 64bit)
リトルエンディアン, 64bit long long:
"\001\002\003\004\005\006\007\010\377\376\375\374\373\372\371\370".unpack("Q*") => [578437695752307201, 17940646550795321087] [578437695752307201, 17940646550795321087].pack("Q*") => "\001\002\003\004\005\006\a\010\377\376\375\374\373\372\371\370" [578437695752307201, -506097522914230529].pack("Q*") => "\001\002\003\004\005\006\a\010\377\376\375\374\373\372\371\370"
m
base64された文字列。60 オクテットごと(と最後)に改行コードが付加されます。
Base64は、3オクテット(8bits * 3 = 24bits)のバイナリコードをASCII文字の うちの65文字 ([A-Za-z0-9+/]の64文字とpaddingのための'=')だけを使用して 4オクテット(6bits * 4 = 24bits)の印字可能文字列に変換するエンコーディ ング法です。RFC2045で定義されています。
[""].pack("m") => "" ["\0"].pack("m") => "AA==\n" ["\0\0"].pack("m") => "AAA=\n" ["\0\0\0"].pack("m") => "AAAA\n" ["\377"].pack("m") => "/w==\n" ["\377\377"].pack("m") => "//8=\n" ["\377\377\377"].pack("m") => "////\n" ["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"].pack("m") => "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJT\nVFVWV1hZWg==\n" ["abcdefghijklmnopqrstuvwxyz"].pack("m3") => "YWJj\nZGVm\nZ2hp\namts\nbW5v\ncHFy\nc3R1\ndnd4\neXo=\n" "".unpack("m") => [""] "AA==\n".unpack("m") => ["\000"] "AA==".unpack("m") => ["\000"] "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJT\nVFVWV1hZWg==\n".unpack("m") => ["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"] "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWg==\n".unpack("m") => ["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"]
M
quoted-printable encoding された文字列
["a b c\td \ne"].pack("M") => "a b c\td =\n\ne=\n" "a b c\td =\n\ne=\n".unpack("M") => ["a b c\td \ne"]
n
ネットワークバイトオーダー(ビッグエンディアン)のunsigned short (16bit 符号なし整数)
[0,1,-1,32767,-32768,65535].pack("n*") => "\000\000\000\001\377\377\177\377\200\000\377\377" "\000\000\000\001\377\377\177\377\200\000\377\377".unpack("n*") => [0, 1, 65535, 32767, 32768, 65535]
N
ネットワークバイトオーダー(ビッグエンディアン)のunsigned long (32bit 符号なし整数)
[0,1,-1].pack("N*") => "\000\000\000\000\000\000\000\001\377\377\377\377" "\000\000\000\000\000\000\000\001\377\377\377\377".unpack("N*") => [0, 1, 4294967295]
v
"VAX"バイトオーダー(リトルエンディアン)のunsigned short (16bit 符号なし整数)
[0,1,-1,32767,-32768,65535].pack("v*") => "\000\000\001\000\377\377\377\177\000\200\377\377" "\000\000\001\000\377\377\377\177\000\200\377\377".unpack("v*") => [0, 1, 65535, 32767, 32768, 65535]
V
"VAX"バイトオーダー(リトルエンディアン)のunsigned long (32bit 符号なし整数)
[0,1,-1].pack("V*") => "\000\000\000\000\001\000\000\000\377\377\377\377" "\000\000\000\000\001\000\000\000\377\377\377\377".unpack("V*") => [0, 1, 4294967295]
f
単精度浮動小数点数(機種依存)
IA-32 (x86) (IEEE754 単精度 リトルエンディアン):
[1.0].pack("f") => "\000\000\200?"
sparc (IEEE754 単精度 ビッグエンディアン):
[1.0].pack("f") => "?\200\000\000"
d
倍精度浮動小数点数(機種依存)
IA-32 (IEEE754 倍精度 リトルエンディアン):
[1.0].pack("d") => "\000\000\000\000\000\000\360?"
sparc (IEEE754 倍精度 ビッグエンディアン):
[1.0].pack("d") => "?\360\000\000\000\000\000\000"
e
リトルエンディアンの単精度浮動小数点数(機種依存)
IA-32:
[1.0].pack("e") => "\000\000\200?"
sparc:
[1.0].pack("e") => "\000\000\200?"
E
リトルエンディアンの倍精度浮動小数点数(機種依存)
IA-32:
[1.0].pack("E") => "\000\000\000\000\000\000\360?"
sparc:
[1.0].pack("E") => "\000\000\000\000\000\000\360?"
g
ビッグエンディアンの単精度浮動小数点数(機種依存)
IA-32:
[1.0].pack("g") => "?\200\000\000"
sparc:
[1.0].pack("g") => "?\200\000\000"
G
ビッグエンディアンの倍精度浮動小数点数(機種依存)
IA-32:
[1.0].pack("G") => "?\360\000\000\000\000\000\000"
sparc:
[1.0].pack("G") => "?\360\000\000\000\000\000\000"
p
ナル終端の文字列へのポインタ
[""].pack("p") => "\310\037\034\010" ["a", "b", "c"].pack("p3") => " =\030\010\340^\030\010\360^\030\010" [nil].pack("p") => "\000\000\000\000"
P
構造体(固定長文字列)へのポインタ
[nil].pack("P") => "\000\000\000\000" ["abc"].pack("P3") => "x*\024\010" ["abc"].pack("P4") => ArgumentError: too short buffer for P(3 for 4) [""].pack("P") => ArgumentError: too short buffer for P(0 for 1)
u
uuencodeされた文字列
[""].pack("u") => "" ["a"].pack("u") => "!80``\n" ["abc"].pack("u") => "#86)C\n" ["abcd"].pack("u") => "$86)C9```\n" ["a"*45].pack("u") => "M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A\n" ["a"*46].pack("u") => "M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A\n!80``\n" ["abcdefghi"].pack("u6") => "&86)C9&5F\n#9VAI\n"
U
UTF-8
[0].pack("U") => "\000" [1].pack("U") => "\001" [0x7f].pack("U") => "\177" [0x80].pack("U") => "\302\200" [0x7fffffff].pack("U") => "\375\277\277\277\277\277" [0x80000000].pack("U") => RangeError [0,256,65536].pack("U3") => "\000\304\200\360\220\200\200" "\000\304\200\360\220\200\200".unpack("U3") => [0, 256, 65536] "\000\304\200\360\220\200\200".unpack("U") => [0] "\000\304\200\360\220\200\200".unpack("U*") => [0, 256, 65536]
w
BER圧縮整数
1バイトあたり7ビットを使用して必要最小限のバイト数で任意サイズの 0以上の整数を表す数値表現。各バイトの最上位ビットはデータの最後 を除いて必ず1が立っている(つまり最上位ビットはどこまでデータがあ るかを示している)。
BER は Basic Encoding Rules の略(BER自体 は整数のエンコーディングだ けを表すわけではない。ASN.1 のエンコーディングで使用される)
[0].pack("w") => "\000" [1].pack("w") => "\001" [127].pack("w") => "\177" [128].pack("w") => "\201\000" [0x3fffffff].pack("w") => "\203\377\377\377\177" [0x40000000].pack("w") => "\204\200\200\200\000" [0xffffffff].pack("w") => "\217\377\377\377\177" [0x100000000].pack("w") => "\220\200\200\200\000" "\0".unpack("w") => [0] "\0\201\0\1".unpack("w*") => [0, 128, 1]
x
ナルバイト/1バイト読み飛ばす
[?a, ?b].pack("CxC") => "a\000b" [?a, ?b].pack("Cx3C") => "a\000\000\000b" "a\000b".unpack("CxC") => [97, 98] "a\377b".unpack("CxC") => [97, 98] "a\377b".unpack("Cx3C") => ArgumentError: x outside of string
X
1バイト後退
[?a, ?b, ?c].pack("CCXC") => "ac" "abcdef".unpack("x*XC") => [102]
@
絶対位置への移動
[?a, ?b].pack("C @3 C") => "a\000\000b" "a\000\000b".unpack("C @3 C") => [97, 98]
以下、pack/unpack の使用例の一部です。
pack を使用しなくても同じことができる場合はその例も載せています。 pack は暗号になりやすい面があることを考慮し、pack を使いたくない人 に別解を示すためです。
数値(文字コード)の配列を文字列に変換する例
p [82, 117, 98, 121].pack("cccc") => "Ruby" p [82, 117, 98, 121].pack("c4") => "Ruby" p [82, 117, 98, 121].pack("c*") => "Ruby" s = "" [82, 117, 98, 121].each {|c| s << c} p s => "Ruby" p [82, 117, 98, 121].collect {|c| sprintf "%c", c}.join => "Ruby" p [82, 117, 98, 121].inject("") {|s, c| s << c} => "Ruby"
文字列を数値(文字コード)の配列に変換する例
p "Ruby".unpack('C*') => [82, 117, 98, 121] a = [] "Ruby".each_byte {|c| a << c} p a => [82, 117, 98, 121]
"x" でナルバイトを埋めることができる
p [82, 117, 98, 121].pack("ccxxcc") => "Ru\000\000by"
"x" で文字を読み飛ばす事が出来る
p "Ru\0\0by".unpack('ccxxcc') => [82, 117, 98, 121]
Hexダンプを数値の配列に変換する例
p "61 62 63 64 65 66".delete(' ').to_a.pack('H*').unpack('C*') => [97, 98, 99, 100, 101, 102] p "61 62 63 64 65 66".split.collect {|c| c.hex} => [97, 98, 99, 100, 101, 102]
バイナリと16進数のpackでは長さ指定は生成されるバイト数ではなく、 ビットやニブルの個数を表す
p [0b01010010, 0b01110101, 0b01100010, 0b01111001].pack("C4") => "Ruby" p ["01010010011101010110001001111001"].pack("B32") # 8 bits * 4 => "Ruby" p [0x52, 0x75, 0x62, 0x79].pack("C4") => "Ruby" p ["52756279"].pack("H8") # 2 nybbles * 4 => "Ruby"
テンプレート文字'a'の長さ指定は1つの文字列だけに適用される
p ["RUBY", "u", "b", "y"].pack("a4") => "RUBY" p ["RUBY", "u", "b", "y"].pack("aaaa") => "Ruby" p ["RUBY", "u", "b", "y"].pack("a*aaa") => "RUBYuby"
テンプレート文字"a"は、長さが足りない分をヌル文字で補う
p ["Ruby"].pack("a8") => "Ruby\000\000\000\000"
リトルエンディアンとビッグエンディアン
p [1,2].pack("s2") => "\000\001\000\002" # ビッグエンディアンのシステムでの出力 => "\001\000\002\000" # リトルエンディアンのシステムでの出力 p [1,2].pack("n2") => "\000\001\000\002" # システムによらずビッグエンディアン p [1,2].pack("v2") => "\001\000\002\000" # システムによらずリトルエンディアン
ネットワークバイトオーダの signed long
s = "\xff\xff\xff\xfe" n = s.unpack("N")[0] if n[31] == 1 n = -((n ^ 0xffff_ffff) + 1) end p n => -2
ネットワークバイトオーダの signed long(その2)
s = "\xff\xff\xff\xfe" p n = s.unpack("N").pack("l").unpack("l")[0] => -2
IPアドレス
require 'socket' p Socket.gethostbyname("localhost")[3].unpack("C4").join(".") => "127.0.0.1" p "127.0.0.1".split(".").collect {|c| c.to_i}.pack("C4") => "\177\000\000\001"
sockaddr_in 構造体
require 'socket' p [Socket::AF_INET, Socket.getservbyname('echo'), 127, 0, 0, 1].pack("s n C4 x8") => "\002\000\000\a\177\000\000\001\000\000\000\000\000\000\000\000"
ruby 1.7 feature: pack/unpack を使う代わりに Socket.pack_sockaddr_in, Socket.unpack_sockaddr_in メソッドがあります。
'\0'終端文字列のアドレス
テンプレート文字 "p" や "P" は、C 言語レベルのインタフェースのた めにあります(例えば ioctl)。
p ["foo"].pack("p") => "8\266\021\010"
結果の文字列はゴミに見えますが、実際は文字列"foo\0"を指すアドレ ス(のバイナリ表現)です。以下のようにすれば見慣れた表記で見ること が出来ます
printf "%#010x\n", "8\266\021\010".unpack("L")[0] => 0x0811b638
アドレスが指す先のオブジェクト(この例で "foo\0") は、pack の結 果が GC されるまではGCされないことが保証されています。
unpack("p"), unpack("P") は、pack の結果からしか unpack できません。
p ["foo"].pack("p").unpack("p") => ["foo"] p "8\266\021\010".unpack("p") => -:1:in `unpack': no associated pointer (ArgumentError) from -:1
ruby 1.7 feature: "p" や "P" は、nil を特別に扱い NULL ポインタとして解釈します。(以下は、32bitマシンで一般的な結果)
p [nil].pack("p") #=> "\000\000\000\000" p "\0\0\0\0".unpack("p") #=> [nil]
構造体のアドレス
例えば、
struct { int a; short b; long c; } v = {1,2,3};
を表す文字列は
v = [1,2,3].pack("i!s!l!")
です。(byte alignment の問題から実際は適当な padding が必要に なるかもしれません)
この構造体を指すアドレスは
p [v].pack("P") => "\300\265\021\010"
で得られます。
*1 `_' は、Perl の真似だったようですが、Perl が途中で '!' に変えたため
Ruby ではこれら2つが残ったんだそうです
*2あらい: 2001-04-22 もっとちゃんと調べてから書こう。上記は信用
しないように:p 誰か代わりにしっかりしたのを書いてくれても良いです
ちなみに ISO 8825 です