tags:

views:

78

answers:

2

Can I format an Erlang binary so that each byte is written in hex? I.e.,

> io:format(???, [<<255, 16>>]).
<<FF, 10>>

I don't see an obvious way to do it in io:format documentation, but perhaps I am simply missing one? Converting a binary to list and formatting its elements separately is too inefficient.

+3  A: 

No, there is not such formating option but you can do something like:

io:format("<<~s>>~n", [[io_lib:format("~2.16B",[X]) || <<X:8>> <= <<255,16>> ]]).

But there are may be better and faster solution for your purpose.

Hynek -Pichi- Vychodil
+1  A: 

You could do: [ hd(erlang:integer_to_list(Nibble, 16)) || << Nibble:4 >> <= Binary ].

Which would return you a list(string) containing the hex digits of the binary. While I doubt the efficiency of this operation is going to have any effect on the runtime of your system, you could also have this bin_to_hex function return an iolist which is simpler to construct and will be flattened when output anyway. The following function returns an iolist with the formatting example you gave:

bin_to_hex(Bin) when is_binary(Bin) ->
    JoinableLength = byte_size(Bin) - 1,
    << Bytes:JoinableLength/binary, LastNibble1:4, LastNibble2:4 >> = Bin,
    [ "<< ",
      [ [ erlang:integer_to_list(Nibble1, 16), erlang:integer_to_list(Nibble2, 16), ", " ]
        || << Nibble1:4, Nibble2:4 >> <= Bytes ],
      erlang:integer_to_list(LastNibble1, 16),
      erlang:integer_to_list(LastNibble2, 16),
      " >>" ].

It's a bit ugly, but runs through the binary once and doesn't traverse the output list (otherwise I'd have used string:join to get the interspersed ", " sequences). If this function is not the inner loop of some process (I have a hard time believing this function will be your bottleneck), then you should probably go with some trivially less efficient, but far more obvious code like:

bin_to_hex(Bin) when is_binary(Bin) ->
    "<< " ++ string:join([byte_to_hex(B) || << B >> <= Bin ],", ") ++ " >>".

byte_to_hex(<< N1:4, N2:4 >>) ->
    [erlang:integer_to_list(N1, 16), erlang:integer_to_list(N2, 16)].
archaelus