【问题标题】:How do I concatenate two binaries in Erlang?如何在 Erlang 中连接两个二进制文件?
【发布时间】:2010-10-10 16:21:22
【问题描述】:

如何在 Erlang 中连接两个二进制文件?

例如,假设我有:

B1 = <<1,2>>.
B2 = <<3,4>>.

如何连接 B1 和 B2 以创建二进制 B3,即 >?

我问这个的原因是因为我正在编写代码来为某些网络协议编码数据包。我通过为数据包中的字段编写编码器来实现这一点,我需要连接这些字段以构建整个数据包。

也许我这样做是错误的。我应该将数据包构建为整数列表并在最后一刻将列表转换为二进制吗?

【问题讨论】:

    标签: erlang binaries


    【解决方案1】:
    28> B1= <<1,2>>.
    <<1,2>>
    29> B2= <<3,4>>.
    <<3,4>>
    30> B3= <<B1/binary, B2/binary>>.
    <<1,2,3,4>>
    31>
    

    【讨论】:

    • 大概这不是一个 O(1) 操作,因此按照 cthulahoops 的建议构建一个深度列表(IO 列表)并推迟遍历深度列表直到我准备好发送仍然有意义包?
    • 两个答案都很好。 io_list cthulahoops 的结构非常适合 i/o;但是,由于这现在是“erlang concatenate binaries”的热门 google 搜索结果,因此很高兴在这里也能得到严格正确的答案。
    【解决方案2】:

    您可以使用位语法连接二进制文件:

    1> B1 = <<1,2>>.
    <<1,2>>
    2> B2 = <<3,4>>.
    <<3,4>>
    3> B3 = <<B1/binary, B2/binary>>.
    <<1,2,3,4>>
    

    在许多情况下,特别是在数据以网络为目标的情况下,您可以通过构建 io_list 来避免串联。

    B3 = [B1, B2],
    gen_tcp:send(Socket, B3).
    

    这是 O(1),因为它避免了复制任何一个二进制文件。 gen_tcp:send 将接受深度列表并遍历结构以进行输出。 (两元素列表占用的额外内存非常少,因此内存开销很小。)

    在某些情况下(重复附加到同一个二进制文件),Erlang 现在进行了优化,可以避免复制附加到的二进制文件,因此使用 io_lists 可能不太相关:http://erlang.org/doc/efficiency_guide/binaryhandling.html#constructing-binaries


    历史记录:我最初只建议 io_list 解决方案,并且很多评论者正确指出我没有回答这个问题。希望现在接受的答案是完整的。 (11 年后!)

    【讨论】:

    • 谢谢!我对 Erlang 中的深度列表和 io 列表的概念并不熟悉。
    • 我不认为这个代码是正确的。它返回:[&lt;&lt;1,2&gt;&gt;,&lt;&lt;3,4&gt;&gt;] 这不是@Cayle Spandon 所要求的。所以答案是错误的。
    • @Worker - cthulahoops 给出的答案并不是要实际连接两个二进制文件。这个答案的重点是,如果您正在使用的代码将接受 iolists,那么您首先可以避免连接两个二进制文件的计算成本。由于最初的提问者说他​​们正在尝试构建一个网络数据包,因此这个答案表明,连接两个二进制文件可能并不是实现原始提问者所需的最佳方式。
    • @Nick 此答案不回答 [main, titled] 问题,因此无效。我来到这里是因为我不得不在 Erlang 中连接两个二进制文件来解决一个完全不同的问题。这也是 OP 在一个问题中提出两个不同问题的错误,但这是 google 上针对通用问题“我如何连接两个二进制文件和 Erlang”的最佳答案,它没有回答这个问题。
    • OP 也是一个粗心的 SO 用户,因为他接受了标题为“如何在 Erlang 中连接两个二进制文件?”的问题的答案。回答说“不要”。这会扰乱未来的搜索者。
    【解决方案3】:

    要使用 io_list,您可以这样做:

    erlang:iolist_to_binary([<<"foo">>, <<"bar">>])
    

    这很好而且清晰。如果更方便的话,你也可以使用列表和里面的东西。

    【讨论】:

      【解决方案4】:

      以最后一个答案为基础:

      bjoin(List) ->
          F = fun(A, B) -> <<A/binary, B/binary>> end,
          lists:foldr(F, <<>>, List).
      

      【讨论】:

        【解决方案5】:

        使用 erlang 函数 list_to_binary(List) 你可以在这里找到文档: http://www.erlang.org/documentation/doc-5.4.13/lib/kernel-2.10.13/doc/html/erlang.html#list_to_binary/1

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-08-27
          • 2010-09-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多