【问题标题】:Parsing ASCII characters with Erlang用 Erlang 解析 ASCII 字符
【发布时间】:2015-09-04 23:35:23
【问题描述】:

对需要进行什么解析以及在客户端/服务器端进行什么感到困惑。

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

在此之后,我将其作为推送通知(通过 GCM/APNS 静默)发送给我的客户。从那里开始,客户端通过 UTF-8 解码对每个数字一个一个进行构建(这是错误的)。

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

如果要处理两个字节或三个或更多字节,则此重建需要识别。 这因字母的语言而异(此处为德语)。

客户端如何识别它要重构的语言(一次解码的字节数)?

要添加更多,

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}"

我给了“hi”作为消息,而 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 被重构时,我重构的消息都是胡言乱语。

谢谢

【问题讨论】:

  • 这和解析无关。可能您的 json 编码不正确。
  • @Mickaël 我按照这里所说的 mochijson 编码进行了操作:tiliman.wordpress.com/2013/01/02/… 我猜这个问题可能是其他问题。你认为我的 erlang 模块应该传递什么 {data ,[{message,Message} ?我正在向 GCM 服务器发送 ASCII。
  • 我遇到了一些 json 库的问题。尝试使用另一个或另一个版本以确保。
  • 你能给我推荐 mochijson 和 mochijson2 的替代品吗?还有你用的什么?
  • 你也尝试过 mochijson 吗?我认为对于某些东西我使用 mochijson 和其他一些 mochijson2。

标签: android erlang xmpp apple-push-notifications ejabberd


【解决方案1】:

这里要担心的事情有很多,并且与所需的编码或数据结构有关。在 Erlang 中,文本以下列方式之一处理:

  1. 字节列表 ([0..255, ...])
    • 如果您侦听套接字并将数据作为列表返回,这就是您得到的结果。
    • VM 假定没有编码。它们是字节,意义不大。
    • 但是,VM 可以将这些解释为字符串(例如在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。
    • 这些列表代表您在 unicode 标准中看到的代码点,没有任何编码(它们不是UTF-x
    • 这可以与 latin-1 字符列表结合使用,因为 Unicode 代码点和 latin1 字符在 255 以下具有相同的序列号。
  3. 二进制文件 (&lt;&lt;0..255, ...&gt;&gt;)
    • 这就是您收听或阅读 binary 格式下的任何内容时所获得的结果。
    • 可以告诉 VM 假设许多事情:
      1. 它们是字节序列 (0..255),没有特定含义 (&lt;&lt;Bin/binary&gt;&gt;)
      2. 它们是 utf-8 编码序列 (&lt;&lt;Bin/utf-8&gt;&gt;)
      3. 它们是 utf-16 编码序列 (&lt;&lt;Bin/utf-16&gt;&gt;)
      4. 它们是 utf-32 编码序列 (&lt;&lt;Bin/utf-32&gt;&gt;)
    • io:format("~s~n", [Bin]) 仍将假定任何序列都是 latin-1 序列; io:format("~ts~n", [Bin]) 将仅假定 UTF-8
  4. Unicode 列表和 utf 编码二进制文件的混合列表(称为 iodata()),专门用于输出。

总而言之:

  • 字节列表
  • latin-1 字符列表
  • Unicode 代码点列表
  • 二进制字节
  • utf-8 二进制
  • utf-16 二进制
  • utf-32 二进制
  • 其中许多列表用于快速连接的输出

还要注意:在 17.0 版之前,所有 Erlang 源文件都是 latin-1 的。 17.0 添加了一个选项,让编译器通过添加此标头将源文件读取为 unicode:

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

下一个因素是,根据规范,JSON 假定 UTF-8 作为它所拥有的所有内容的编码。此外,Erlang 中的 JSON 库倾向于假设二进制文件是字符串,而列表是 JSON 数组。

这意味着,如果您希望输出足够,则必须使用 UTF-8 编码的二进制文件来表示任何 JSON。

如果你拥有的是:

  • 代表 utf 编码字符串的字节列表,然后是 list_to_binary(List) 以获得正确的二进制表示
  • 代码点列表,然后使用unicode:characters_to_binary(List, unicode, utf8) 获取 utf-8 编码的二进制文件
  • 表示 latin-1 字符串的二进制文件:unicode:characters_to_binary(Bin, latin1, utf8)
  • 任何其他 UTF 编码的二进制文件:unicode:characters_to_binary(Bin, utf16 | utf32, utf8)

获取该 UTF-8 二进制文件,并将其发送到 JSON 库。如果 JSON 库是正确的并且客户端可以正确解析它,那么它应该是正确的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-15
    • 1970-01-01
    • 2012-06-23
    相关资源
    最近更新 更多