Здравствуйте, я пытался понять, как работать с двоичными файлами в Эликсире, и я пытался разобрать строку

"2018-04-07 13:00:00.000000"

Я хотел получить их часть года и сделал следующее

date = "2018-04-07 13:00:00.000000"
<< d::size(80), rest::binary >> = date

Теперь, когда я пытаюсь отдохнуть, я получаю все после свидания, включая пробел

" 13:00:00.000000"

Но если я пытаюсь получить d, я действительно не понимаю, что получаю, но результат следующий

237007314493411930484791

Не могли бы вы, ребята, помочь понять, что происходит.

Спасибо.

1
Kirill kilo-code Babkin 14 Мар 2018 в 04:52

2 ответа

Лучший ответ

Решение вашей проблемы - использовать binary-size следующим образом: << d::binary-size(10), rest::binary >> = date

После выдержки из документации следует уточнить соответственно:

Битовая строка состоит из множества сегментов, и каждый сегмент имеет тип. В битовых строках используются 9 типов: - integer - float - bits (псевдоним для bitstring) - bitstring - binary - bytes (псевдоним для binary) - utf8 - utf16 - utf32 Если тип не указан, по умолчанию используется integer

Например, << d::integer-size(80), rest::binary >> = date дал бы вам тот же результат, что и вы сообщили.

4
Kevin Johnson 14 Мар 2018 в 02:20

Хотя ответ Кевина Джонсона прекрасно объясняет, как обращаться с двоичными файлами, я опубликую объяснение того, что произошло на самом деле.

Бинарный файл в Erlang (и, следовательно, в Elixir) может быть создан с использованием значений ASCII для символов:

iex|1 ▶ <<50, 48>>
#⇒ "20"

Когда вы сопоставляете образец с size(80), вы фактически сопоставляете образец с 10 позициями целого числа в 256-основном. По сути, произошло вот что:

iex|2 ▶ <<a1::size(8), a2::size(8), a3::size(8),
          a4::size(8), a5::size(8), a6::size(8),
          a7::size(8), a8::size(8), a9::size(8),
          a10::size(8), _ :: binary>> = "2018-04-07 13..."
#⇒ "2018-04-07 13..."

Давайте проверим наши значения (да, массив целых чисел по возможности распечатывается как битовая строка, обратите внимание на одинарные кавычки ):

iex|3 ▶ [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10] 
#⇒ '2018-04-07'

Хорошо, пока все хорошо. Давайте теперь получим результат из приведенных выше целых чисел. Это было бы:

a10 * 1 + a9 * 256 + a8 * 256² + ...

Или, используя ограниченные арифметические способности Эликсира:

iex|4 ▶ [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10]
...|4 ▷ |> Enum.reverse
...|4 ▷ |> Enum.with_index
...|4 ▷ |> Enum.reduce(0, fn {e, i}, acc ->
...|4 ▷                     # ⇓⇓⇓ exact integer i-power of 256 ⇓⇓⇓
...|4 ▷      acc + e * Enum.reduce(List.duplicate(256, i), 1, &Kernel.*/2)
...|4 ▷ end)
#⇒ 237007314493411930484791

Это именно то, что вы получили, когда попросили сопоставить первые 10 позиций по образцу с 10-значным числом на основе 256.

5
Aleksei Matiushkin 14 Мар 2018 в 07:31