Erlang Central

Decoding Binary Messages

From ErlangCentral Wiki


You have a string containing the characters 0 and 1, representing, in binary, the ASCII values of some text. You want to convert this string into normal, readable, ASCII.


This would probably be an appropriate place to demonstrate some of Erlang's built-in support for communicating with remote systems, converting text into binary format, and so forth. But, we will save those topics for their own recipes. This topic will be treated as was done in the original Schematics Cookbook.


decode_message(L) -> decode_message(L,[]).
decode_message([],Acc) -> lists:reverse(Acc);
decode_message(L,Acc) ->
    {BinC,T} = lists:split(8,L),
    {ok,[C],[]} = io_lib:fread("~2u",BinC),

%% The following message appeared on a ThinkGeek tshirt
%% on the first of april 2004.
1> bin:decode_message(
1>     "010010010010000001110011011010000110111"
1>     "101110000011100000110010101100100001000" 
1>     "000110000101110100001000000101010001101" 
1>     "000011010010110111001101011010001110110" 
1>     "010101100101011010110010000001101111011"
1>     "011100010000001000001011100000111001001" 
1>     "101001011011000010000001000110011011110" 
1>     "110111101101100011100110010000001000100" 
1>     "011000010111100100101100001000000110000" 
1>     "101101110011001000010000001100001011011" 
1>     "000110110000100000010010010010000001100" 
1>     "111011011110111010000100000011101110110" 
1>     "000101110011001000000111010001101000011" 
1>     "010010111001100100000011011000110111101" 
1>     "110101011100110111100100100000011100110" 
1>     "110100001101001011100100111010000100001").
"I shopped at ThinkGeek on April Fools Day, and all I got was this lousy shirt!

The Erlang system comes with io_lib functions to convert from strings to numbers (via io_lib:fread) and vice-versa (via io_lib:format). For example:

2> io_lib:fread("~d", "100").
% Note:  The "d" is just an aspect of Erlang's odd handling of
% strings as lists of decimal numbers.  The ASCII value of the
% character "d" is 100:
3> $d.
4> io_lib:format("~B", [100]).

Both procedures take an additional argument which specifies the radix ("base") to use. The default is 10, but values of 2 through 36 may also be used. In the recipe above the radix 2 (format of "~2u") specifies that we are converting to numbers from a base 2 representation. If, for example, the numbers were represented in base 16 (hexadecimal) it would be a simple matter to use "~16u" instead.