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