【问题标题】:What type of format is this in ERLANG. Doesnt look like JSON?在 ERLANG 中这是什么类型的格式。看起来不像 JSON?
【发布时间】:2018-07-30 18:52:40
【问题描述】:

我刚刚使用file:write 转储了这个变量:

file:write_file("/tmp/foo.txt", io_lib:fwrite("~p.\n", [Message])),

这是 emqtt 中插件代码的一部分。 我想解析这些内容并在消息变量中获取部分 sdfjksdf,在名为主题的变量中获取 home/garden/fountain。这个怎么做。我不知道二郎。

{mqtt_message,<<0,5,101,163,106,150,123,212,110,126,0,0,76,244,0,3>>,
              undefined,
              {<<"1852fadb884d46c7a349f6a974846ce1">>,undefined},
              <<"home/garden/fountain">>,0,[],false,false,false,[],
              <<"sdfjksdf">>,
              {1519,127425,874902}}

这是我遇到问题的功能

on_message_publish(Message, _Env) ->
    io:format("publish ~s~n", [emqttd_message:format(Message)]),
    file:write_file("/tmp/foo.txt", io_lib:fwrite("~p.\n", [Message])),
    inets:start(),
    Method = post,
    URL = "http://xyz.in/api/v2/mysql/_table/device",
    Header = [{"Api-Key", "1234"}],
    Type = "application/json",
    Body = "{\"resource\":[{\"deviceid\":\"" ++ "msg" ++ "\"}]}",
    HTTPOptions = [],
    Options = [],
    R = httpc:request(Method, {URL, Header, Type, Body}, HTTPOptions, Options),
    {ok, Message}.

在上面的代码中,我必须从 Message 对象传递字符串“sdfjksdf”并发送代替“msg”字符串。 我试过 ++ element(12,Message) ++ 但它不起作用。

然后我尝试了 ++ binary_to_list(element(12,Message)) ++ 这也不起作用。

我如何通过连接将消息对象中的字符串“sdfjksdf”作为 JSON 字符串中的参数传递给函数。

【问题讨论】:

  • 你不应该在这个问题中添加你关于 Erlang 的所有问题。不要超载它。自己创建新的或(甚至更好)开始搜索答案。

标签: erlang mqtt erlang-shell


【解决方案1】:

这是 erlang 中的一个元组。请参阅:http://erlang.org/doc/reference_manual/data_types.html。这是用单独的行上的每个元素组织的元组:

{
    mqtt_message,
    <<0,5,101,163,106,150,123,212,110,126,0,0,76,244,0,3>>,
    undefined,
    {<<"1852fadb884d46c7a349f6a974846ce1">>,undefined},
    <<"home/garden/fountain">>,
    0,
    [],
    false,
    false,
    false,
    [],
    <<"sdfjksdf">>,
    {1519,127425,874902}
}

元组中第一个元素的索引是 1。所以你可以这样做:

8> Data = f:get_data().
{mqtt_message,<<0,5,101,163,106,150,123,212,110,126,0,0,
                76,244,0,3>>,
              undefined,
              {<<"1852fadb884d46c7a349f6a974846ce1">>,undefined},
              <<"home/garden/fountain">>,0,[],false,false,false,[],
              <<"sdfjksdf">>,
              {1519,127425,874902}}

9> Message = element(12, Data).
<<"sdfjksdf">>

10> Topic = element(5, Data).
<<"home/garden/fountain">>

对评论的回应:

请问上面的>符号是什么意思 元组

如果您搜索了我在上面发布的链接的页面,其中列出了所有 erlang 数据类型,您会发现这样的元素:

<<"sdfjksdf">>

被称为二进制。二进制文件就像字符串,但对于二进制文件,erlang 提供了一种语法,允许您将二进制文件分割成您想要的任何大小的位块。这对于读取通过网络发送的字符串非常有用,因为前 4 位可能代表整个消息的长度,接下来的 12 位代表一些信息,接下来的 3 位代表一些其他信息,等等。

但是由于二进制文件也比字符串更有效,即使您不需要将字符串分割成其组成位,您也可以将字符串转换为二进制文件并传递它们。 erlang 中的所有 I/O 工具都可以比字符串更有效地处理二进制文件。

但是,如果出于某种原因您需要将二进制文件作为字符串,您可以使用函数binary_to_list() 将二进制文件转换为字符串。在 erlang 中,字符串实际上是一个 list,其中包含整数字符代码:

9> [97,98,99].
"abc"

...因此命名为 binary_to_list。

这是一个将二进制转换为字符串的示例:

7> TopicBin = <<"home/garden/fountain">>.
<<"home/garden/fountain">>

8> TopicStr = binary_to_list(TopicBin).
"home/garden/fountain"
9> 

对编辑的回应:

我试过++ element(12,Message) ++ 但它不起作用。

我们已经确定element(12, Message) 的返回值是二进制文件,但您应该检查以确保:

X = element(12, Message),
io:format("What is this: ~w~n", [X])

接下来,++ 运算符是 string:concat() 的快捷方式,它需要字符串参数,因此您不能将 ++ 与二进制文件一起使用。

然后我尝试了++ binary_to_list(element(12,Message)) ++ 这也不起作用。

这行得通:

2> Msg = "sdfjksdf".
"sdfjksdf"

3> Result = "hello " ++ Msg ++ " world".
"hello sdfjksdf world"

之前,我们讨论了如何将二进制文件转换为字符串(列表)。所以,你可以这样做:

5> Bin = <<"sdfjksdf">>.
<<"sdfjksdf">>

6> Msg = binary_to_list(Bin).   
"sdfjksdf"

7> "hello " ++ Msg ++ " world".

而且,最后一行相当于:

8> "hello " ++ binary_to_list(Bin) ++ " world".
"hello sdfjksdf world"

它在你的函数内部:

-module(f).
-compile(export_all).

get_message() ->
{
    mqtt_message,
    <<0,5,101,163,106,150,123,212,110,126,0,0,76,244,0,3>>,
    undefined,
    {<<"1852fadb884d46c7a349f6a974846ce1">>,undefined},
    <<"home/garden/fountain">>,
    0,
    [],
    false,
    false,
    false,
    [],
    <<"sdfjksdf">>,
    {1519,127425,874902}
}.


on_message_publish(Message, _Env) ->
    %io:format("publish ~s~n", [emqttd_message:format(Message)]),
    %file:write_file("/tmp/foo.txt", io_lib:fwrite("~p.\n", [Message])),
    %inets:start(),
    DeviceIdBin = element(12, Message),
    DeviceIdStr = binary_to_list(DeviceIdBin),

    Method = post,
    URL = "http://xyz.in/api/v2/mysql/_table/device",
    Header = [{"Api-Key", "1234"}],
    Type = "application/json",
    Body = "{\"resource\":[{\"deviceid\":\"" ++ DeviceIdStr ++ "\"}]}",
    io:format("Body=~s~n", [Body]),
    %HTTPOptions = [],
    %Options = [],
    %R = httpc:request(Method, {URL, Header, Type, Body}, HTTPOptions, Options),
    {ok, Message}.


go() ->
    Message = get_message(),
    on_message_publish(Message, "hello").

在 erlang shell 中:

5> c(f).  
f.erl:29: Warning: variable 'Method' is unused
f.erl:30: Warning: variable 'URL' is unused
f.erl:31: Warning: variable 'Header' is unused
f.erl:32: Warning: variable 'Type' is unused
{ok,f}

6> f:go().
Body={"resource":[{"deviceid":"sdfjksdf"}]}
{ok,{mqtt_message,<<0,5,101,163,106,150,123,212,110,126,0,
                    0,76,244,0,3>>,
                  undefined,
                  {<<"1852fadb884d46c7a349f6a974846ce1">>,undefined},
                  <<"home/garden/fountain">>,0,[],false,false,false,[],
                  <<"sdfjksdf">>,
                  {1519,127425,874902}}}
7> 

【讨论】:

  • 非常感谢您的回答。这解释了它。也请你告诉上面元组中 > 符号的含义是什么。现在这就是我将消息写入文件以查看对象结构的样子时的样子。如果不写入文件,我想我可以像 Topic = element(5,Message) 一样访问它,我会尝试这个并更新。
  • @RaviPujar,在我的答案底部查看我的回复。
  • 谢谢,我知道现在是二进制字符串。我已经用我面临的实际问题更新了我的问题。您能否指导一下如何做到这一点。
  • @RaviPujar,在我的帖子底部查看我的回复。
  • 太棒了 :) 它奏效了。刚刚添加了DeviceIdBin = element(12, Message), DeviceIdStr = binary_to_list(DeviceIdBin), 然后 ++ DeviceIdStr ++ 非常感谢:)
【解决方案2】:

该类型称为tuple,是Erlang 数据类型。您通常可以将其视为固定长度的数组。 Erlang 元组是 1 索引的。有几种方法可以从元组中提取数据。如果知道元组的大小,例如:

{_,_,_,_,Message,_,_,_,_,_,_,Topic,_} = {mqtt_message,<<0,5,101,163,106,150,123,212,110,126,0,0,76,244,0,3>>,
              undefined,
              {<<"1852fadb884d46c7a349f6a974846ce1">>,undefined},
              <<"home/garden/fountain">>,0,[],false,false,false,[],
              <<"sdfjksdf">>,
              {1519,127425,874902}}.

这会将您想要的数据分别绑定到 Message 和 Topic 变量。或者使用内置函数element

element(5, {mqtt_message,<<0,5,101,163,106,150,123,212,110,126,0,0,76,244,0,3>>,
              undefined,
              {<<"1852fadb884d46c7a349f6a974846ce1">>,undefined},
              <<"home/garden/fountain">>,0,[],false,false,false,[],
              <<"sdfjksdf">>,
              {1519,127425,874902}}) 

或:

element(12, {mqtt_message,<<0,5,101,163,106,150,123,212,110,126,0,0,76,244,0,3>>,
              undefined,
              {<<"1852fadb884d46c7a349f6a974846ce1">>,undefined},
              <<"home/garden/fountain">>,0,[],false,false,false,[],
              <<"sdfjksdf">>,
              {1519,127425,874902}})

我希望这能回答你的问题,干杯!

编辑: &lt;&lt;&gt;&gt; 是一个 Erlang 二进制文件,这是一个相当大的主题。您可以阅读有关数据类型和内置二进制操作的信息here

编辑2: 我不完全确定您对原始帖子的最后一次编辑是什么意思。但是,如果您想简单地提取二进制 &lt;&lt;"sdfjksdf"&gt;&gt; 并将其附加到现有字符串:

42> Msg = binary:bin_to_list(element(12,Message)).
"sdfjksdf"
43> "test: " ++ Msg.
"test: sdfjksdf"

您需要找出使用该语法将其附加到 JSON 正文中的正确方法。请记住,++ 操作对于大型列表无效。

【讨论】:

  • 非常感谢您的回答。我现在知道了。也请您告诉上面元组中 > 符号的含义。
  • > 是空的 Erlang 二进制数据类型
  • 这可以有一些整数或类似上面的字符。
  • 谢谢,我现在明白了。我已经用我面临的实际问题更新了我的问题。你能否指导如何做到这一点。我无法获取传递给 HTTP 请求的字符串。
  • 我更新了我的答案,试图进一步帮助你,请查看。
猜你喜欢
  • 2011-01-12
  • 1970-01-01
  • 2017-05-11
  • 2016-04-28
  • 2020-02-21
  • 1970-01-01
  • 2016-03-25
  • 2018-09-24
  • 1970-01-01
相关资源
最近更新 更多