打包数据

某些 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]

字符串指令

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

二进制字符串指令

位字符串指令

十六进制字符串指令

指针字符串指令

其他字符串指令

偏移指令

空字节指令