Разбор символов ASCII с помощью Erlang

Путать с тем, что нужно выполнить, и с какой стороны клиент / сервер.

When i send an Umlaut 'Ö' to my ejabberd, 
it is received by ejabberd as <<"195, 150">>

После этого я отправляю это своему клиенту в виде Push-уведомлений (через GCM/APNS без уведомления). Оттуда клиент строит декодирование UTF-8 по каждой цифре одна за другой (это неправильно).

i.e. 195 is first decoded to gibberish character � and so on.

Эта реконструкция требует идентификации, если два байта должны быть заняты или 3 или более. Это зависит от языка букв (например, немецкий здесь).

Как клиент определит, какой язык он собирается реконструировать (количество байтов для декодирования за один раз)?

Чтобы добавить больше,

lists:flatten(mochijson2:encode({struct,[{registration_ids,[Reg_id]},{data ,[{message,Message},{type,Type},{enum,ENUM},{groupid,Groupid},{groupname,Groupname},{sender,Sender_list},{receiver,Content_list}]},{time_to_live,2419200}]})).

Произведено JSON как:

"{\"registration_ids\":[\"APA91bGLjnkhqZlqFEp7mTo9p1vu9s92_A0UIzlUHnhl4xdFTaZ_0HpD5SISB4jNRPi2D7_c8D_mbhUT_k-T2Bo_i_G3Jt1kIqbgQKrFwB3gp1jeGatrOMsfG4gAJSEkClZFFIJEEyow\"],\"data\":{\"message\":[104,105],\"type\":[71,82,79,85,80],\"enum\":2001,\"groupid\":[71,73,68],\"groupname\":[71,114,111,117,112,78,97,109,101],\"sender\":[49,64,100,101,118,108,97,98,47,115,100,115],\"receiver\":[97,115,97,115]},\"time_to_live\":2419200}"

где я дал "привет" в качестве сообщения, а mochijson дал мне значения ASCII [104,105].

The groupname field was given the value "Groupname",
the ASCIIs are also correct after json creation i.e. 71,114,111,117,112,78,97,109,101

Однако, когда я использую http://www.unit-conversion.info/texttools/ascii/

It is decodes as Ǎo��me and not "Groupname".

Итак, кто должен делать анализ? Как то же самое должно быть обработано.

Мое восстановленное сообщение - все это бессмысленно, когда восстанавливается ASCII.

Спасибо

1 ответ

Здесь есть много поводов для беспокойства, связанных с желаемым кодированием или структурой данных. В Erlang текст обрабатывается одним из следующих способов:

  1. списки байтов ([0..255, ...])
    • Это то, что вы получаете, если вы слушаете сокет и данные возвращаются в виде списка.
    • ВМ не предполагает кодирования. Они байты и значат немного больше.
    • Однако виртуальная машина может интерпретировать их как строки (скажем, в io:format("~s~n", [List])). Когда это произойдет (с ~s флаг), VM предполагает, что кодировка latin-1 (ISO-8859-1).
  2. списки кодов Unicode ([0..1114111, ...]).
    • Вы можете получить их из файлов, которые читаются как Unicode и как список.
    • Вы можете использовать их в выводе, когда у вас есть такой форматтер, как io:format("~ts~n", [List]) где ~ts как ~s но как юникод.
    • Эти списки представляют собой кодовые точки, которые вы видите в стандарте Unicode, без какой-либо кодировки (они не являютсяUTF-x)
    • Это может работать в сочетании со списками символов латиницы-1, поскольку кодовые точки Unicode и символы латиницы-1 имеют одинаковые порядковые номера ниже 255.
  3. Двоичные файлы (<<0..255, ...>>)
    • Это то, что вы получаете, если вы слушаете или читаете что-либо под binary формат.
    • ВМ можно сказать, чтобы предполагать много вещей:
      1. Это последовательности байтов (0..255) без конкретного значения (<<Bin/binary>>)
      2. Они представляют собой кодированные последовательности utf-8 (<<Bin/utf-8>>)
      3. Они представляют собой кодированные последовательности utf-16 (<<Bin/utf-16>>)
      4. Это кодированные последовательности utf-32 (<<Bin/utf-32>>)
    • io:format("~s~n", [Bin]) будет по-прежнему предполагать, что любая последовательность является латинской-1; io:format("~ts~n", [Bin]) приду UTF-8 только.
  4. Смешанный список как списков Unicode, так и двоичных файлов в кодировке UTF (известный как iodata()), используется исключительно для вывода.

Итак, в сущности:

  • списки байтов
  • списки латинских символов
  • списки кодов Unicode
  • двоичный байт
  • UTF-8 двоичный
  • двоичный файл utf-16
  • двоичный файл utf-32
  • списки многих из них для вывода, который быстро объединяется

Также обратите внимание: до версии 17.0 все исходные файлы Erlang были только латиницей-1. 17.0 добавили опцию, чтобы компилятор считывал ваш исходный файл как Unicode, добавив этот заголовок:

%% -*- coding: utf-8 -*-

Следующим фактором является то, что JSON, по спецификации, предполагает UTF-8 как кодировка для всего, что у него есть. Кроме того, библиотеки JSON в Erlang будут склонны предполагать, что двоичный файл является строкой, а списки являются массивами JSON.

Это означает, что если вы хотите, чтобы ваш вывод был адекватным, вы должны использовать двоичные файлы в кодировке UTF-8 для представления любого JSON.

Если то, что у вас есть:

  • Список байтов, представляющих строку в кодировке utf, затем list_to_binary(List) чтобы получить правильное двоичное представление
  • Список кодовых точек, затем используйте unicode:characters_to_binary(List, unicode, utf8) получить кодированный в кодировке utf-8
  • Двоичный файл, представляющий строку из латиницы-1: unicode:characters_to_binary(Bin, latin1, utf8)
  • Двоичный файл любой другой кодировки UTF: unicode:characters_to_binary(Bin, utf16 | utf32, utf8)

Возьмите этот двоичный файл UTF-8 и отправьте его в библиотеку JSON. Если библиотека JSON верна и клиент правильно ее анализирует, то она должна быть правильной.

Другие вопросы по тегам