Упакованные данные
Краткая справка
В этих таблицах приведены директивы для упаковки и распаковки.
Для целых чисел
Directive | Meaning
--------------|---------------------------------------------------------------
C | 8-bit unsigned (unsigned char)
S | 16-bit unsigned, native endian (uint16_t)
L | 32-bit unsigned, native endian (uint32_t)
Q | 64-bit unsigned, native endian (uint64_t)
J | pointer width unsigned, native endian (uintptr_t)
c | 8-bit signed (signed char)
s | 16-bit signed, native endian (int16_t)
l | 32-bit signed, native endian (int32_t)
q | 64-bit signed, native endian (int64_t)
j | pointer width signed, native endian (intptr_t)
S_ S! | unsigned short, native endian
I I_ I! | unsigned int, native endian
L_ L! | unsigned long, native endian
Q_ Q! | unsigned long long, native endian
| (raises ArgumentError if the platform has no long long type)
J! | uintptr_t, native endian (same with J)
s_ s! | signed short, native endian
i i_ i! | signed int, native endian
l_ l! | signed long, native endian
q_ q! | signed long long, native endian
| (raises ArgumentError if the platform has no long long type)
j! | intptr_t, native endian (same with j)
S> s> S!> s!> | each the same as the directive without >, but big endian
L> l> L!> l!> | S> is the same as n
I!> i!> | L> is the same as N
Q> q> Q!> q!> |
J> j> J!> j!> |
S< s< S!< s!< | each the same as the directive without <, but little endian
L< l< L!< l!< | S< is the same as v
I!< i!< | L< is the same as V
Q< q< Q!< q!< |
J< j< J!< j!< |
n | 16-bit unsigned, network (big-endian) byte order
N | 32-bit unsigned, network (big-endian) byte order
v | 16-bit unsigned, VAX (little-endian) byte order
V | 32-bit unsigned, VAX (little-endian) byte order
U | UTF-8 character
w | BER-compressed integer Для чисел с плавающей точкой
Directive | Meaning ----------|-------------------------------------------------- D d | double-precision, native format F f | single-precision, native format E | double-precision, little-endian byte order e | single-precision, little-endian byte order G | double-precision, network (big-endian) byte order g | single-precision, network (big-endian) byte order
Для строк
Directive | Meaning
----------|-----------------------------------------------------------------
A | arbitrary binary string (remove trailing nulls and ASCII spaces)
a | arbitrary binary string
Z | null-terminated string
B | bit string (MSB first)
b | bit string (LSB first)
H | hex string (high nibble first)
h | hex string (low nibble first)
u | UU-encoded string
M | quoted-printable, MIME encoding (see RFC2045)
m | base64 encoded string (RFC 2045) (default)
| (base64 encoded string (RFC 4648) if followed by 0)
P | pointer to a structure (fixed-length string)
p | pointer to a null-terminated string Дополнительные директивы для упаковки
Directive | Meaning ----------|---------------------------------------------------------------- @ | moves to absolute position X | back up a byte x | null byte
Дополнительные директивы для распаковки
Directive | Meaning ----------|---------------------------------------------------------------- @ | skip to the offset given by the length argument X | skip backward one byte x | skip forward one byte
Упаковка и распаковка
Некоторые методы ядра 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] -
Integercount— директива применяется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 quoted-printable; текстовый режим, при этом входные данные должны использовать 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:[""].pack("u") # => "" ["a"].pack("u") # => "!80``\n" ["aaa"].pack("u") # => "#86%A\n" "".unpack("u") # => [""] "#86)C\n".unpack("u") # => ["abc"]
Директивы смещения
-
'@'— начать упаковку с указанного смещения в байтах; при упаковке при необходимости заполнить нулевыми байтами или уменьшить размер:[1, 2].pack("C@0C") # => "\x02" [1, 2].pack("C@1C") # => "\x01\x02" [1, 2].pack("C@5C") # => "\x01\x00\x00\x00\x00\x02" [*1..5].pack("CCCC@2C") # => "\x01\x02\x05"При распаковке нельзя перейти за пределы строки:
"\x01\x00\x00\x02".unpack("C@3C") # => [1, 2] "\x00".unpack("@1C") # => [nil] "\x00".unpack("@2C") # Raises ArgumentError. -
'X'— при упаковке уменьшить размер до указанного смещения в байтах:[0, 1, 2].pack("CCXC") # => "\x00\x02" [0, 1, 2].pack("CCX2C") # => "\x02"При распаковке — переместить позицию распаковки назад на указанное смещение в байтах:
"\x00\x02".unpack("CCXC") # => [0, 2, 2]Нельзя перейти за пределы строки:
[0, 1, 2].pack("CCX3C") # Raises ArgumentError. "\x00\x02".unpack("CX3C") # Raises ArgumentError. -
'x'— начать упаковку после указанного смещения в байтах; при упаковке при необходимости заполнить нулевыми байтами:[].pack("x0") # => "" [].pack("x") # => "\x00" [].pack("x8") # => "\x00\x00\x00\x00\x00\x00\x00\x00"При распаковке нельзя перейти за пределы строки:
"\x00\x00\x02".unpack("CxC") # => [0, 2] "\x00\x00\x02".unpack("x3C") # => [nil] "\x00\x00\x02".unpack("x4C") # Raises ArgumentError
Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.