打包数据

某些 Ruby 核心方法处理数据的打包和解包

这些方法中的每一个都接受一个字符串 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]

任何指令都可以后跟以下任意修饰符

如果元素不符合提供的指令,则仅编码最低有效位

[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#unpackString#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 位整数指令

16 位整数指令

32 位整数指令

64 位整数指令

平台相关整数指令

其他整数指令

整数指令的修饰符

对于以下指令,'!''_' 修饰符可以作为底层平台的本机大小的后缀。

对于始终为本机大小的指令,本机大小修饰符将被忽略。

字节序修饰符也可以作为上述指令的后缀

浮点数指令

每个浮点数指令指定输入或输出数组中一个元素的打包或解包。

单精度浮点数指令

双精度浮点数指令

浮点数指令可以是无穷大或非数字

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]

字符串指令

每个字符串指令指定输入或输出字符串中一个字节的打包或解包。

二进制字符串指令

位字符串指令

十六进制字符串指令

指针字符串指令

其他字符串指令

偏移指令

空字节指令