封裝資料¶ ↑
某些 Ruby 核心方法處理資料的封裝和解封裝
-
方法
Array#pack
: 將陣列self
中的每個元素格式化為二進制字串;傳回該字串。 -
方法
String#unpack
:從字串self
中萃取資料,形成成為新陣列元素的物件;傳回該陣列。 -
方法
String#unpack1
:執行相同動作,但只解壓縮並傳回第一個萃取的物件。
這些方法每個都接受一個字串 template
,包含零個或多個指令字元,每個字元後接零個或多個修飾詞字元。
範例(指令 'C'
指定「無符號字元」)
[65].pack('C') # => "A" # One element, one directive. [65, 66].pack('CC') # => "AB" # Two elements, two directives. [65, 66].pack('C') # => "A" # Extra element is ignored. [65].pack('') # => "" # No directives. [65].pack('CC') # Extra directive raises ArgumentError. 'A'.unpack('C') # => [65] # One character, one directive. 'AB'.unpack('CC') # => [65, 66] # Two characters, two directives. 'AB'.unpack('C') # => [65] # Extra character is ignored. 'A'.unpack('CC') # => [65, nil] # Extra directive generates nil. 'AB'.unpack('') # => [] # No directives.
字串 template
可以包含任何有效指令的組合(指令 'c'
指定「有符號字元」)
[65, -1].pack('cC') # => "A\xFF" "A\xFF".unpack('cC') # => [65, 255]
字串 template
可以包含空白(會忽略)和註解,每個註解都以字元 '#'
開頭,並持續到下一個換行字元(包含換行字元)
[0,1].pack(" C #foo \n C ") # => "\x00\x01" "\0\1".unpack(" C #foo \n C ") # => [0, 1]
任何指令都可以接續下列這些修飾詞
-
'*'
- 指令會根據需要套用多次[65, 66].pack('C*') # => "AB" 'AB'.unpack('C*') # => [65, 66]
-
Integer
count
- 指令會套用count
次[65, 66].pack('C2') # => "AB" [65, 66].pack('C3') # Raises ArgumentError. 'AB'.unpack('C2') # => [65, 66] 'AB'.unpack('C3') # => [65, 66, nil]
注意:
%w[A a Z m]
中的指令以不同的方式使用count
;請參閱 字串指令。
如果元素不符合提供的指令,只會編碼最低有效位元
[257].pack("C").unpack("C") # => [1]
封裝方法¶ ↑
方法 Array#pack
接受選用的關鍵字引數 buffer
,指定目標字串(而不是新字串)
[65, 66].pack('C*', buffer: 'foo') # => "fooAB"
該方法可以接受區塊
# Packed string is passed to the block. [65, 66].pack('C*') {|s| p s } # => "AB"
解壓縮方法¶ ↑
方法 String#unpack
和 String#unpack1
各接受選用的關鍵字引數 offset
,指定字串中的偏移量
'ABC'.unpack('C*', offset: 1) # => [66, 67] 'ABC'.unpack1('C*', offset: 1) # => 66
這兩個方法都可以接受區塊
# Each unpacked object is passed to the block. ret = [] "ABCD".unpack("C*") {|c| ret << c } ret # => [65, 66, 67, 68] # The single unpacked object is passed to the block. 'AB'.unpack1('C*') {|ele| p ele } # => 65
整數指令¶ ↑
每個整數指令都指定輸入或輸出陣列中一個元素的封裝或解壓縮。
8 位元整數指令¶ ↑
-
'c'
- 8 位元有符號整數(例如 Csigned char
)[0, 1, 255].pack('c*') # => "\x00\x01\xFF" s = [0, 1, -1].pack('c*') # => "\x00\x01\xFF" s.unpack('c*') # => [0, 1, -1]
-
'C'
- 8 位元無符號整數(例如 Cunsigned char
)[0, 1, 255].pack('C*') # => "\x00\x01\xFF" s = [0, 1, -1].pack('C*') # => "\x00\x01\xFF" s.unpack('C*') # => [0, 1, 255]
16 位元整數指令¶ ↑
-
's'
- 16 位元有號整數,本機端序(例如 Cint16_t
)[513, -514].pack('s*') # => "\x01\x02\xFE\xFD" s = [513, 65022].pack('s*') # => "\x01\x02\xFE\xFD" s.unpack('s*') # => [513, -514]
-
'S'
- 16 位元無號整數,本機端序(例如 Cuint16_t
)[513, -514].pack('S*') # => "\x01\x02\xFE\xFD" s = [513, 65022].pack('S*') # => "\x01\x02\xFE\xFD" s.unpack('S*') # => [513, 65022]
-
'n'
- 16 位元網路整數,大端序s = [0, 1, -1, 32767, -32768, 65535].pack('n*') # => "\x00\x00\x00\x01\xFF\xFF\x7F\xFF\x80\x00\xFF\xFF" s.unpack('n*') # => [0, 1, 65535, 32767, 32768, 65535]
-
'v'
- 16 位元 VAX 整數,小端序s = [0, 1, -1, 32767, -32768, 65535].pack('v*') # => "\x00\x00\x01\x00\xFF\xFF\xFF\x7F\x00\x80\xFF\xFF" s.unpack('v*') # => [0, 1, 65535, 32767, 32768, 65535]
32 位元整數指令¶ ↑
-
'l'
- 32 位元有號整數,本機端序(例如 Cint32_t
)s = [67305985, -50462977].pack('l*') # => "\x01\x02\x03\x04\xFF\xFE\xFD\xFC" s.unpack('l*') # => [67305985, -50462977]
-
'L'
- 32 位元無號整數,本機端序(例如 Cuint32_t
)s = [67305985, 4244504319].pack('L*') # => "\x01\x02\x03\x04\xFF\xFE\xFD\xFC" s.unpack('L*') # => [67305985, 4244504319]
-
'N'
- 32 位元網路整數,大端序s = [0,1,-1].pack('N*') # => "\x00\x00\x00\x00\x00\x00\x00\x01\xFF\xFF\xFF\xFF" s.unpack('N*') # => [0, 1, 4294967295]
-
'V'
- 32 位元 VAX 整數,小端序s = [0,1,-1].pack('V*') # => "\x00\x00\x00\x00\x01\x00\x00\x00\xFF\xFF\xFF\xFF" s.unpack('v*') # => [0, 0, 1, 0, 65535, 65535]
64 位元整數指令¶ ↑
-
'q'
- 64 位元有號整數,本機端序(例如 Cint64_t
)s = [578437695752307201, -506097522914230529].pack('q*') # => "\x01\x02\x03\x04\x05\x06\a\b\xFF\xFE\xFD\xFC\xFB\xFA\xF9\xF8" s.unpack('q*') # => [578437695752307201, -506097522914230529]
-
'Q'
- 64 位元無號整數,本機端序(例如 Cuint64_t
)s = [578437695752307201, 17940646550795321087].pack('Q*') # => "\x01\x02\x03\x04\x05\x06\a\b\xFF\xFE\xFD\xFC\xFB\xFA\xF9\xF8" s.unpack('Q*') # => [578437695752307201, 17940646550795321087]
平台相關整數指令¶ ↑
-
'i'
- 平台相關寬度有號整數,本機端序(例如 Cint
)s = [67305985, -50462977].pack('i*') # => "\x01\x02\x03\x04\xFF\xFE\xFD\xFC" s.unpack('i*') # => [67305985, -50462977]
-
'I'
- 平台相關寬度無號整數,本機端序(例如 Cunsigned int
)s = [67305985, -50462977].pack('I*') # => "\x01\x02\x03\x04\xFF\xFE\xFD\xFC" s.unpack('I*') # => [67305985, 4244504319]
-
'j'
- 指標寬度有號整數,本機端序(例如 Cintptr_t
)s = [67305985, -50462977].pack('j*') # => "\x01\x02\x03\x04\x00\x00\x00\x00\xFF\xFE\xFD\xFC\xFF\xFF\xFF\xFF" s.unpack('j*') # => [67305985, -50462977]
-
'J'
- 指標寬度無號整數,本機端序(例如 Cuintptr_t
)s = [67305985, 4244504319].pack('J*') # => "\x01\x02\x03\x04\x00\x00\x00\x00\xFF\xFE\xFD\xFC\x00\x00\x00\x00" s.unpack('J*') # => [67305985, 4244504319]
其他整數指令¶ ↑
-
'U'
- UTF-8 字元s = [4194304].pack('U*') # => "\xF8\x90\x80\x80\x80" s.unpack('U*') # => [4194304]
-
'w'
- BER 編碼整數(請參閱 BER 編碼)s = [1073741823].pack('w*') # => "\x83\xFF\xFF\xFF\x7F" s.unpack('w*') # => [1073741823]
整數指令的修飾詞¶ ↑
對於下列指令,'!'
或 '_'
修飾詞可用作底層平台的本機大小。
-
'i'
,'I'
- Cint
,始終為本機大小。 -
's'
,'S'
- Cshort
。 -
'l'
,'L'
- Clong
。 -
'q'
,'Q'
- Clong long
(如果可用)。 -
'j'
,'J'
- Cintptr_t
,始終為本機大小。
對於始終為本機大小的指令,本機大小修飾詞會被自動忽略。
上述指令中也可以加上端序修飾詞
-
'>'
- 大端序。 -
'<'
- 小端序。
浮點指令¶ ↑
每個浮點指令指定輸入或輸出陣列中一個元素的封裝或解封裝。
單精度浮點指令¶ ↑
-
'F'
或'f'
- 本機格式s = [3.0].pack('F') # => "\x00\x00@@" s.unpack('F') # => [3.0]
-
'e'
- 小端序s = [3.0].pack('e') # => "\x00\x00@@" s.unpack('e') # => [3.0]
-
'g'
- 大端序s = [3.0].pack('g') # => "@@\x00\x00" s.unpack('g') # => [3.0]
雙精度浮點指令¶ ↑
-
'D'
或'd'
- 原生格式s = [3.0].pack('D') # => "\x00\x00\x00\x00\x00\x00\b@" s.unpack('D') # => [3.0]
-
'E'
- 小端序s = [3.0].pack('E') # => "\x00\x00\x00\x00\x00\x00\b@" s.unpack('E') # => [3.0]
-
'G'
- 大端序s = [3.0].pack('G') # => "@\b\x00\x00\x00\x00\x00\x00" s.unpack('G') # => [3.0]
浮點指令可以是無限大或非數字
inf = 1.0/0.0 # => Infinity [inf].pack('f') # => "\x00\x00\x80\x7F" "\x00\x00\x80\x7F".unpack('f') # => [Infinity] nan = inf/inf # => NaN [nan].pack('f') # => "\x00\x00\xC0\x7F" "\x00\x00\xC0\x7F".unpack('f') # => [NaN]
字串指令¶ ↑
每個字串指令指定輸入或輸出字串中一個位元組的封裝或解封裝。
二進制字串指令¶ ↑
-
'A'
- 任意二進制字串(空白填充;計數為寬度);nil
視為空字串['foo'].pack('A') # => "f" ['foo'].pack('A*') # => "foo" ['foo'].pack('A2') # => "fo" ['foo'].pack('A4') # => "foo " [nil].pack('A') # => " " [nil].pack('A*') # => "" [nil].pack('A2') # => " " [nil].pack('A4') # => " " "foo\0".unpack('A') # => ["f"] "foo\0".unpack('A4') # => ["foo"] "foo\0bar".unpack('A10') # => ["foo\x00bar"] # Reads past "\0". "foo ".unpack('A') # => ["f"] "foo ".unpack('A4') # => ["foo"] "foo".unpack('A4') # => ["foo"] russian = "\u{442 435 441 442}" # => "тест" russian.size # => 4 russian.bytesize # => 8 [russian].pack('A') # => "\xD1" [russian].pack('A*') # => "\xD1\x82\xD0\xB5\xD1\x81\xD1\x82" russian.unpack('A') # => ["\xD1"] russian.unpack('A2') # => ["\xD1\x82"] russian.unpack('A4') # => ["\xD1\x82\xD0\xB5"] russian.unpack('A*') # => ["\xD1\x82\xD0\xB5\xD1\x81\xD1\x82"]
-
'a'
- 任意二進制字串(空值填充;計數為寬度)["foo"].pack('a') # => "f" ["foo"].pack('a*') # => "foo" ["foo"].pack('a2') # => "fo" ["foo\0"].pack('a4') # => "foo\x00" [nil].pack('a') # => "\x00" [nil].pack('a*') # => "" [nil].pack('a2') # => "\x00\x00" [nil].pack('a4') # => "\x00\x00\x00\x00" "foo\0".unpack('a') # => ["f"] "foo\0".unpack('a4') # => ["foo\x00"] "foo ".unpack('a4') # => ["foo "] "foo".unpack('a4') # => ["foo"] "foo\0bar".unpack('a4') # => ["foo\x00"] # Reads past "\0".
-
'Z'
- 與'a'
相同,但空值會使用'*'
新增或忽略["foo"].pack('Z*') # => "foo\x00" [nil].pack('Z*') # => "\x00" "foo\0".unpack('Z*') # => ["foo"] "foo".unpack('Z*') # => ["foo"] "foo\0bar".unpack('Z*') # => ["foo"] # Does not read past "\0".
位元字串指令¶ ↑
-
'B'
- 位元字串(高位元組優先)['11111111' + '00000000'].pack('B*') # => "\xFF\x00" ['10000000' + '01000000'].pack('B*') # => "\x80@" ['1'].pack('B0') # => "" ['1'].pack('B1') # => "\x80" ['1'].pack('B2') # => "\x80\x00" ['1'].pack('B3') # => "\x80\x00" ['1'].pack('B4') # => "\x80\x00\x00" ['1'].pack('B5') # => "\x80\x00\x00" ['1'].pack('B6') # => "\x80\x00\x00\x00" "\xff\x00".unpack("B*") # => ["1111111100000000"] "\x01\x02".unpack("B*") # => ["0000000100000010"] "".unpack("B0") # => [""] "\x80".unpack("B1") # => ["1"] "\x80".unpack("B2") # => ["10"] "\x80".unpack("B3") # => ["100"]
-
'b'
- 位元字串(低位元組優先)['11111111' + '00000000'].pack('b*') # => "\xFF\x00" ['10000000' + '01000000'].pack('b*') # => "\x01\x02" ['1'].pack('b0') # => "" ['1'].pack('b1') # => "\x01" ['1'].pack('b2') # => "\x01\x00" ['1'].pack('b3') # => "\x01\x00" ['1'].pack('b4') # => "\x01\x00\x00" ['1'].pack('b5') # => "\x01\x00\x00" ['1'].pack('b6') # => "\x01\x00\x00\x00" "\xff\x00".unpack("b*") # => ["1111111100000000"] "\x01\x02".unpack("b*") # => ["1000000001000000"] "".unpack("b0") # => [""] "\x01".unpack("b1") # => ["1"] "\x01".unpack("b2") # => ["10"] "\x01".unpack("b3") # => ["100"]
十六進制字串指令¶ ↑
-
'H'
- 十六進制字串(高半位元組優先)['10ef'].pack('H*') # => "\x10\xEF" ['10ef'].pack('H0') # => "" ['10ef'].pack('H3') # => "\x10\xE0" ['10ef'].pack('H5') # => "\x10\xEF\x00" ['fff'].pack('H3') # => "\xFF\xF0" ['fff'].pack('H4') # => "\xFF\xF0" ['fff'].pack('H5') # => "\xFF\xF0\x00" ['fff'].pack('H6') # => "\xFF\xF0\x00" ['fff'].pack('H7') # => "\xFF\xF0\x00\x00" ['fff'].pack('H8') # => "\xFF\xF0\x00\x00" "\x10\xef".unpack('H*') # => ["10ef"] "\x10\xef".unpack('H0') # => [""] "\x10\xef".unpack('H1') # => ["1"] "\x10\xef".unpack('H2') # => ["10"] "\x10\xef".unpack('H3') # => ["10e"] "\x10\xef".unpack('H4') # => ["10ef"] "\x10\xef".unpack('H5') # => ["10ef"]
-
'h'
- 十六進制字串(低半位元組優先)['10ef'].pack('h*') # => "\x01\xFE" ['10ef'].pack('h0') # => "" ['10ef'].pack('h3') # => "\x01\x0E" ['10ef'].pack('h5') # => "\x01\xFE\x00" ['fff'].pack('h3') # => "\xFF\x0F" ['fff'].pack('h4') # => "\xFF\x0F" ['fff'].pack('h5') # => "\xFF\x0F\x00" ['fff'].pack('h6') # => "\xFF\x0F\x00" ['fff'].pack('h7') # => "\xFF\x0F\x00\x00" ['fff'].pack('h8') # => "\xFF\x0F\x00\x00" "\x01\xfe".unpack('h*') # => ["10ef"] "\x01\xfe".unpack('h0') # => [""] "\x01\xfe".unpack('h1') # => ["1"] "\x01\xfe".unpack('h2') # => ["10"] "\x01\xfe".unpack('h3') # => ["10e"] "\x01\xfe".unpack('h4') # => ["10ef"] "\x01\xfe".unpack('h5') # => ["10ef"]
指標字串指令¶ ↑
-
'P'
- 指向結構的指標(固定長度字串)s = ['abc'].pack('P') # => "\xE0O\x7F\xE5\xA1\x01\x00\x00" s.unpack('P*') # => ["abc"] ".".unpack("P") # => [] ("\0" * 8).unpack("P") # => [nil] [nil].pack("P") # => "\x00\x00\x00\x00\x00\x00\x00\x00"
-
'p'
- 指向空值終止字串的指標s = ['abc'].pack('p') # => "(\xE4u\xE5\xA1\x01\x00\x00" s.unpack('p*') # => ["abc"] ".".unpack("p") # => [] ("\0" * 8).unpack("p") # => [nil] [nil].pack("p") # => "\x00\x00\x00\x00\x00\x00\x00\x00"
其他字串指令¶ ↑
-
'M'
- 可列印引號,MIME 編碼;文字模式,但輸入必須使用 LF 且輸出 LF;(請參閱 RFC 2045)["a b c\td \ne"].pack('M') # => "a b c\td =\n\ne=\n" ["\0"].pack('M') # => "=00=\n" ["a"*1023].pack('M') == ("a"*73+"=\n")*14+"a=\n" # => true ("a"*73+"=\na=\n").unpack('M') == ["a"*74] # => true (("a"*73+"=\n")*14+"a=\n").unpack('M') == ["a"*1023] # => true "a b c\td =\n\ne=\n".unpack('M') # => ["a b c\td \ne"] "=00=\n".unpack('M') # => ["\x00"] "pre=31=32=33after".unpack('M') # => ["pre123after"] "pre=\nafter".unpack('M') # => ["preafter"] "pre=\r\nafter".unpack('M') # => ["preafter"] "pre=".unpack('M') # => ["pre="] "pre=\r".unpack('M') # => ["pre=\r"] "pre=hoge".unpack('M') # => ["pre=hoge"] "pre==31after".unpack('M') # => ["pre==31after"] "pre===31after".unpack('M') # => ["pre===31after"]
-
'm'
-Base64
編碼字串;計數指定每個換行符號之間的輸入位元組,向下捨入到最接近的 3 的倍數;如果計數為零,則不新增換行符號;(請參閱 RFC 4648)[""].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" "".unpack('m') # => [""] "AA==\n".unpack('m') # => ["\x00"] "AAA=\n".unpack('m') # => ["\x00\x00"] "AAAA\n".unpack('m') # => ["\x00\x00\x00"] "/w==\n".unpack('m') # => ["\xFF"] "//8=\n".unpack('m') # => ["\xFF\xFF"] "////\n".unpack('m') # => ["\xFF\xFF\xFF"] "A\n".unpack('m') # => [""] "AA\n".unpack('m') # => ["\x00"] "AA=\n".unpack('m') # => ["\x00"] "AAA\n".unpack('m') # => ["\x00\x00"] [""].pack('m0') # => "" ["\0"].pack('m0') # => "AA==" ["\0\0"].pack('m0') # => "AAA=" ["\0\0\0"].pack('m0') # => "AAAA" ["\377"].pack('m0') # => "/w==" ["\377\377"].pack('m0') # => "//8=" ["\377\377\377"].pack('m0') # => "////" "".unpack('m0') # => [""] "AA==".unpack('m0') # => ["\x00"] "AAA=".unpack('m0') # => ["\x00\x00"] "AAAA".unpack('m0') # => ["\x00\x00\x00"] "/w==".unpack('m0') # => ["\xFF"] "//8=".unpack('m0') # => ["\xFF\xFF"] "////".unpack('m0') # => ["\xFF\xFF\xFF"]
-
'u'
- UU 編碼字串[0].pack("U") # => "\u0000" [0x3fffffff].pack("U") # => "\xFC\xBF\xBF\xBF\xBF\xBF" [0x40000000].pack("U") # => "\xFD\x80\x80\x80\x80\x80" [0x7fffffff].pack("U") # => "\xFD\xBF\xBF\xBF\xBF\xBF"
偏移指令¶ ↑
-
'@'
- 從指定的位元組偏移量開始封裝;對於封裝,必要時填入空值[1, 2].pack("C@0C") # => "\x02" [1, 2].pack("C@1C") # => "\x01\x02" [1, 2].pack("C@5C") # => "\x01\x00\x00\x00\x00\x02" "\x01\x00\x00\x02".unpack("C@3C") # => [1, 2] "\x00".unpack("@1C") # => [nil]
-
'X'
- 備份一個位元組[0, 1, 2].pack("CCXC") # => "\x00\x02" [0, 1, 2].pack("CCX2C") # => "\x02" "\x00\x02".unpack("CCXC") # => [0, 2, 2]
空值位元組指令¶ ↑
-
'x'
- 空值位元組[].pack("x0") # => "" [].pack("x") # => "\x00" [].pack("x8") # => "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x02".unpack("CxC") # => [0, 2]