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 ↑