Packed Data

Certain Ruby core methods deal with packing and unpacking data:

Each of these methods accepts a string template, consisting of zero or more directive characters, each followed by zero or more modifier characters.

Examples (directive 'C' specifies ‘unsigned character’):

[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.

The string template may contain any mixture of valid directives (directive 'c' specifies ‘signed character’):

[65, -1].pack('cC')  # => "A\xFF"
"A\xFF".unpack('cC') # => [65, 255]

The string template may contain whitespace (which is ignored) and comments, each of which begins with character '#' and continues up to and including the next following newline:

[0,1].pack("  C  #foo \n  C  ")    # => "\x00\x01"
"\0\1".unpack("  C  #foo \n  C  ") # => [0, 1]

Any directive may be followed by either of these modifiers:

If elements don’t fit the provided directive, only least significant bits are encoded:

[257].pack("C").unpack("C") # => [1]

Packing Method

Method Array#pack accepts optional keyword argument buffer that specifies the target string (instead of a new string):

[65, 66].pack('C*', buffer: 'foo') # => "fooAB"

The method can accept a block:

# Packed string is passed to the block.
[65, 66].pack('C*') {|s| p s }    # => "AB"

Unpacking Methods

Methods String#unpack and String#unpack1 each accept an optional keyword argument offset that specifies an offset into the string:

'ABC'.unpack('C*', offset: 1)  # => [66, 67]
'ABC'.unpack1('C*', offset: 1) # => 66

Both methods can accept a block:

# 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

Integer Directives

Each integer directive specifies the packing or unpacking for one element in the input or output array.

8-Bit Integer Directives

16-Bit Integer Directives

32-Bit Integer Directives

64-Bit Integer Directives

Platform-Dependent Integer Directives

Pointer Directives

Other Integer Directives

:

Modifiers for Integer Directives

For directives in 'i', 'I', 's', 'S', 'l', 'L', 'q', 'Q', 'j', and 'J', these modifiers may be suffixed:

Float Directives

Each float directive specifies the packing or unpacking for one element in the input or output array.

Single-Precision Float Directives

Double-Precision Float Directives

A float directive may be infinity or not-a-number:

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]

String Directives

Each string directive specifies the packing or unpacking for one byte in the input or output string.

Binary String Directives

Bit String Directives

Hex String Directives

Pointer String Directives

Other String Directives

Offset Directives

Null Byte Direcive