55

How do I concatenate two binaries in Erlang?

For example, let's say I have:

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

How do I concatenate B1 and B2 to create a binary B3 which is <<1,2,3,4>>?

The reason I am asking this is because I am writing code to encode a packet for some networking protocol. I am implementing this by writing encoders for the fields in the packet and I need to concatenate those fields to build up the whole packet.

Maybe I am doing this the wrong way. Should I build up the packet as a list of integers and convert the list to a binary at the last moment?

Bruno Rijsman
  • 3,715
  • 4
  • 31
  • 61

5 Answers5

131
28> B1= <<1,2>>.
<<1,2>>
29> B2= <<3,4>>.
<<3,4>>
30> B3= <<B1/binary, B2/binary>>.
<<1,2,3,4>>
31>
  • Presumably this is not an O(1) operation, so it would still make sense to build a deep list (IO list) as suggested by cthulahoops and postpone walking the deep list until I am ready to send the packet? – Bruno Rijsman Mar 02 '09 at 15:07
  • 18
    Both answers are good. `io_list` structures from cthulahoops are ideal for i/o; however since this is now the top google hit for "erlang concatenate binaries", it's nice to have the strictly correct answer here too. – JasonSmith Dec 20 '10 at 08:44
41

You can concatenate binaries using bit syntax:

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

In many cases, particularly where the data is destined for the network you can avoid the concatenation by constructing an io_list instead.

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

This is O(1) as it avoids copying either binary. gen_tcp:send will accept the deep list and walk the structure for output. (A two element list takes very little additional memory, so the memory overhead is small.)

In some cases (repeated appends to the same binary), Erlang now has optimisations that avoid copying the binary being appended to so using io_lists may be less relevant: http://erlang.org/doc/efficiency_guide/binaryhandling.html#constructing-binaries


Historical note: I originally advised only the io_list solution and a lot of commenters correctly point out that I failed to answer the question. Hopefully, the accepted answer is now complete. (11 years later!)

cthulahoops
  • 3,805
  • 20
  • 17
  • Thanks! I was not familiar with the concepts of deep lists and io lists in Erlang. – Bruno Rijsman Mar 02 '09 at 00:51
  • 25
    I don't this that code is right. It returns : `[<<1,2>>,<<3,4>>]` and this is not what @Cayle Spandon asked for. So answer is wrong. – Worker Feb 16 '12 at 12:02
  • 5
    @Worker - the answer cthulahoops gave isn't intended to actually concatenate the two binaries. The point of this answer is that you can avoid the computational cost of concatenating the two binaries in the first place, if the code you're working with will accept iolists. Since the original questioner said they were trying to build a network packet, this answer suggests that maybe concatenating the two binaries isn't really the best way to achieve what the original questioner needs. – Nick Feb 05 '16 at 19:18
  • 2
    @Nick This answer does not answer the [main, titled] question and thus is not valid. I came here because I had to concatenate two binaries in Erlang for a completely different problem. This is also the OPs fault for asking two different questions in one, but this is the top answer on google for the generic problem "how do I concatenate two binaries and Erlang", and it does not answer that question. – Tommy Feb 11 '16 at 01:31
  • OP is also a careless SO user for accepting the answer of the question titled "How do I concatenate two binaries in Erlang?" with an answer that says "don't". This messes up future searchers. – Tommy Feb 11 '16 at 01:34
  • According to the [efficiency guide](http://erlang.org/doc/efficiency_guide/binaryhandling.html) after version R12B came out (around the time this question was asked) bitstring concatenation does not impose such big a penalty; appending to the 'same' binary multiple times can actually be more efficient (space-wise) than creating iolists – bottlenecked Aug 20 '16 at 17:22
  • Finally fixing this answer! Thanks for all the comments! – cthulahoops Aug 20 '20 at 11:10
22

To use an io_list, you could do:

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

Which is nice and legible. You could also use lists and things in there if it's more convenient.

David N. Welton
  • 1,875
  • 18
  • 33
13

To build on the last answer:

bjoin(List) ->
    F = fun(A, B) -> <<A/binary, B/binary>> end,
    lists:foldr(F, <<>>, List).
pommonico
  • 471
  • 1
  • 5
  • 5
8

use the erlang function list_to_binary(List) you can find the documentation here: http://www.erlang.org/documentation/doc-5.4.13/lib/kernel-2.10.13/doc/html/erlang.html#list_to_binary/1

john nowlin
  • 135
  • 10
Logan Capaldo
  • 39,555
  • 5
  • 63
  • 78