packテンプレート文字列

以下にあげるものは、Array#packString#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"
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") => ArgumentError
[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 のエンコーディングで使用される)

*2

x

ナルバイト/1バイト読み飛ばす

X

1バイト後退

@

絶対位置への移動

使用例

以下、pack/unpack の使用例の一部です。

pack を使用しなくても同じことができる場合はその例も載せています。 pack は暗号になりやすい面があることを考慮し、pack を使いたくない人 に別解を示すためです。


*1 `_' は、Perl の真似だったようですが、Perl が途中で '!' に変えたため Ruby ではこれら2つが残ったんだそうです
*2あらい: 2001-04-22 もっとちゃんと調べてから書こう。上記は信用 しないように:p 誰か代わりにしっかりしたのを書いてくれても良いです ちなみに ISO 8825 です