前言
- 1> term_to_binary(a).
- <<131,100,0,1,97>>
- 2> term_to_binary(1).
- <<131,97,1>>
- 3> term_to_binary({a,b,c}).
- <<131,104,3,100,0,1,97,100,0,1,98,100,0,1,99>>
- 4> binary_to_term(v(1)).
- a
- 5> binary_to_term(v(2)).
- 1
- 6> binary_to_term(v(3)).
- {a,b,c}
初识binary数据
erlang长整形
10.18 SMALL_BIG_EXT
Bignums are stored in unary form with a Sign byte that is 0 if the binum is positive and 1 if is negative. The digits are stored with the LSB byte stored first. To calculate the integer the following formula can be used: |
实际上,erlang一个长整形会被“切分”成多个段,每个段数据用8位表示。公式为:(d0*B^0 + d1*B^1 + d2*B^2 + ... d(N-1)*B^(n-1)), 其中,B = 256
所以,理论上erlang数字可以无限长。
erlang原子
10.7 ATOM_EXT
An atom is stored with a 2 byte unsigned length in big-endian order, followed by Len numbers of 8 bit Latin1 characters that forms theAtomName. Note: The maximum allowed value for Len is 255. |
erlang原子会转成字符串,所以,太长会影响二进制封包大小。
erlang浮点数
10.6 FLOAT_EXT
A float is stored in string format. the format used in sprintf to format the float is "%.20e" (there are more bytes allocated than necessary). To unpack the float use sscanf with format "%lf". |
以上是旧版本erlang浮点数的表示方式,一个erlang浮点数就使用了31个字节来表示,相当浪费。
10.26 NEW_FLOAT_EXT
A float is stored as 8 bytes in big-endian IEEE format. This term is used in minor version 1 of the external format. |
以上的新版的erlang浮点数表示,使用了8个字节来表示一个浮点数,精简了很多。
- Eshell V5.9.1 (abort with ^G)
- 1> term_to_binary(19.2).
- <<131,99,49,46,57,49,57,57,57,57,57,57,57,57,57,57,57,57,
- 57,57,48,48,48,48,101,43,48,48,49,...>>
- Eshell V6.2 (abort with ^G)
- 1> term_to_binary(19.2).
- <<131,70,64,51,51,51,51,51,51,51>>
erlang列表
10.16 LIST_EXT
Length is the number of elements that follows in the Elements section. Tail is the final tail of the list; it is NIL_EXT for a proper list, but may be anything type if the list is improper (for instance [a|b]). |
- -module(test).
- -compile(export_all).
- term_to_data(Term) ->
- Bin = term_to_binary(Term),
- binary_to_data(Bin).
- binary_to_data(<<131, Bin/binary>>) ->
- binary_to_data1(Bin);
- binary_to_data(_) ->
- error.
- -define(NEW_FLOAT_EXT, 70).
- -define(SMALL_INTEGER_EXT, 97).
- -define(INTEGER_EXT, 98).
- -define(FLOAT_EXT, 99).
- -define(ATOM_EXT, 100).
- -define(SMALL_TUPLE_EXT, 104).
- -define(LARGE_TUPLE_EXT, 105).
- -define(NIL_EXT, 106).
- -define(STRING_EXT, 107).
- -define(LIST_EXT, 108).
- -define(BINARY_EXT, 109).
- -define(SMALL_BIG_EXT, 110).
- -define(LARGE_BIG_EXT, 111).
- -define(SMALL_ATOM_EXT, 115).
- binary_to_data1(<<?LARGE_TUPLE_EXT, _ElemtSize:32, Bin/binary>>) ->
- binary_to_data1(Bin);
- binary_to_data1(<<?SMALL_TUPLE_EXT, _ElemtSize:8, Bin/binary>>) ->
- binary_to_data1(Bin);
- binary_to_data1(<<?SMALL_INTEGER_EXT, Int:8, Bin/binary>>) ->
- msg(int, Int),
- binary_to_data1(Bin);
- binary_to_data1(<<?INTEGER_EXT, Int:32, Bin/binary>>) ->
- msg(int2, Int),
- binary_to_data1(Bin);
- binary_to_data1(<<?FLOAT_EXT, Float:31/binary, Bin/binary>>) ->
- F=erlang:binary_to_float(Float),
- msg(float, F),
- binary_to_data1(Bin);
- binary_to_data1(<<?NEW_FLOAT_EXT, Float:64/unsigned-big-float, Bin/binary>>) ->
- msg(float2, Float),
- binary_to_data1(Bin);
- binary_to_data1(<<?SMALL_BIG_EXT, N:8, _Sign:8, Bin:N/binary, Rest/binary>>) ->
- {N, Big} = gen_small_big(Bin),
- msg(big, Big),
- binary_to_data1(Rest);
- binary_to_data1(<<?LARGE_BIG_EXT, N:32, _Sign:8, Bin:N/binary, Rest/binary>>) ->
- {N, Big} = gen_small_big(Bin),
- msg(big2, Big),
- binary_to_data1(Rest);
- binary_to_data1(<<?ATOM_EXT, Len:16, Bin:Len/binary, Rest/binary>>) ->
- msg(atom, erlang:binary_to_atom(Bin, latin1)),
- binary_to_data1(Rest);
- binary_to_data1(<<?SMALL_ATOM_EXT, Len:8, Bin:Len/binary, Rest/binary>>) ->
- msg(atom2, erlang:binary_to_atom(Bin, latin1)),
- binary_to_data1(Rest);
- binary_to_data1(<<?STRING_EXT, Len:16, Bin:Len/binary, Rest/binary>>) ->
- msg(string, Bin),
- binary_to_data1(Rest);
- binary_to_data1(<<?BINARY_EXT, Len:32, Bin:Len/binary, Rest/binary>>) ->
- msg(binary, Bin),
- binary_to_data1(Rest);
- binary_to_data1(<<?LIST_EXT, _ElemtSize:32, Bin/binary>>) ->
- %%msg(list, Bin),
- binary_to_data1(Bin);
- binary_to_data1(<<?NIL_EXT, Rest/binary>>) ->
- %%msg(list_nil, []),
- binary_to_data1(Rest);
- binary_to_data1(<<>>) ->
- ok;
- binary_to_data1(Bin) ->
- msg(unknown, Bin).
- gen_small_big(<<Bin/binary>>) ->
- gen_small_big(Bin, 0, 0).
- gen_small_big(<<>>, Number, Index) ->
- {Index, Number};
- gen_small_big(<<Num:8, Rest/binary>>, Number, Index) ->
- gen_small_big(Rest, Number + Num * (1 bsl (Index * 8)), Index+1).
- msg(Type, Data) ->
- io:format("~w ~w~n", [Type,Data]),
- ok.
- 7> c(test).
- {ok,test}
- 8> test:term_to_data({a,1,"abc"}).
- atom a
- int 1
- string <<97,98,99>>
- ok
- 9> term_to_binary(11111111111111).
- <<131,110,6,0,199,177,212,1,27,10>>
- 10> test:binary_to_data(term_to_binary(11111111111111)).
- big 11111111111111
- ok
实现binary_to_term
- -module(test).
- -compile(export_all).
- term_to_data(Term) ->
- Bin = term_to_binary(Term),
- binary_to_data(Bin).
- binary_to_data(<<131, Bin/binary>>) ->
- binary_to_data1(Bin, [], []);
- binary_to_data(_) ->
- error.
- -define(NEW_FLOAT_EXT, 70).
- -define(SMALL_INTEGER_EXT, 97).
- -define(INTEGER_EXT, 98).
- -define(FLOAT_EXT, 99).
- -define(ATOM_EXT, 100).
- -define(SMALL_TUPLE_EXT, 104).
- -define(LARGE_TUPLE_EXT, 105).
- -define(NIL_EXT, 106).
- -define(STRING_EXT, 107).
- -define(LIST_EXT, 108).
- -define(BINARY_EXT, 109).
- -define(SMALL_BIG_EXT, 110).
- -define(LARGE_BIG_EXT, 111).
- -define(SMALL_ATOM_EXT, 115).
- binary_to_data2( DataList, SizeList, Data) ->
- DataList1 = case Data of
- undefined -> DataList;
- _ -> [Data|DataList]
- end,
- case SizeList of
- [{Type, Size, Index}|R] ->
- Index1 = Index +1,
- case Size=:=Index1 of
- true ->
- {List, DataList2} = split_list(Type, DataList1, Size, []),
- DataList3 = gen_data_block(Type, List, DataList2),
- case R of
- [_|_] ->
- binary_to_data2( DataList3, R, undefined);
- _ ->
- {DataList3, R}
- end;
- _ ->
- {DataList1, [{Type, Size, Index1}|R]}
- end;
- _ ->
- {DataList1, SizeList}
- end.
- split_list(list, [[]|TailList], Size, List) ->
- split_list(list, TailList, Size-1, List);
- split_list(_Type, [], _Size, List) ->
- {List,[]};
- split_list(_Type, TailList, 0, List) ->
- {List, TailList};
- split_list(Type, [Data|TailList], Size, List) ->
- split_list(Type, TailList, Size-1, [Data|List]).
- gen_data_block(tuple, List, DataList) ->
- [list_to_tuple(List)|DataList];
- gen_data_block(list, List, DataList) ->
- [List|DataList].
- binary_to_data1(<<?LARGE_TUPLE_EXT, ElemtSize:32, Bin/binary>>, DataList, SizeList) ->
- binary_to_data1(Bin, DataList, [{tuple, ElemtSize, 0}|SizeList]);
- binary_to_data1(<<?SMALL_TUPLE_EXT, ElemtSize:8, Bin/binary>>, DataList, SizeList) ->
- binary_to_data1(Bin, DataList, [{tuple, ElemtSize, 0}|SizeList]);
- binary_to_data1(<<?SMALL_INTEGER_EXT, Int:8, Bin/binary>>, DataList, SizeList) ->
- %%msg(int, Int),
- {DataList1, SizeList1} = binary_to_data2( DataList, SizeList, Int),
- binary_to_data1(Bin, DataList1, SizeList1);
- binary_to_data1(<<?INTEGER_EXT, Int:32, Bin/binary>>, DataList, SizeList) ->
- %%msg(int2, Int),
- {DataList1, SizeList1} = binary_to_data2( DataList, SizeList, Int),
- binary_to_data1(Bin, DataList1, SizeList1);
- binary_to_data1(<<?FLOAT_EXT, F:31/binary, Bin/binary>>, DataList, SizeList) ->
- Float = erlang:binary_to_float(F),
- %%msg(float, Float),
- {DataList1, SizeList1} = binary_to_data2( DataList, SizeList, Float),
- binary_to_data1(Bin, DataList1, SizeList1);
- binary_to_data1(<<?NEW_FLOAT_EXT, Float:64/unsigned-big-float, Bin/binary>>, DataList, SizeList) ->
- %%msg(float2, Float),
- {DataList1, SizeList1} = binary_to_data2( DataList, SizeList, Float),
- binary_to_data1(Bin, DataList1, SizeList1);
- binary_to_data1(<<?SMALL_BIG_EXT, N:8, _Sign:8, Bin:N/binary, Rest/binary>>, DataList, SizeList) ->
- {N, Big} = gen_small_big(Bin),
- %%msg(big, Big),
- {DataList1, SizeList1} = binary_to_data2( DataList, SizeList, Big),
- binary_to_data1(Rest, DataList1, SizeList1);
- binary_to_data1(<<?LARGE_BIG_EXT, N:32, _Sign:8, Bin:N/binary, Rest/binary>>, DataList, SizeList) ->
- {N, Big} = gen_small_big(Bin),
- %%msg(big2, Big),
- {DataList1, SizeList1} = binary_to_data2( DataList, SizeList, Big),
- binary_to_data1(Rest, DataList1, SizeList1);
- binary_to_data1(<<?ATOM_EXT, Len:16, Bin:Len/binary, Rest/binary>>, DataList, SizeList) ->
- Atom = erlang:binary_to_atom(Bin, latin1),
- %%msg(atom, Atom),
- {DataList1, SizeList1} = binary_to_data2( DataList, SizeList, Atom),
- binary_to_data1(Rest, DataList1, SizeList1);
- binary_to_data1(<<?SMALL_ATOM_EXT, Len:8, Bin:Len/binary, Rest/binary>>, DataList, SizeList) ->
- Atom = erlang:binary_to_atom(Bin, latin1),
- %%msg(atom2, Atom),
- {DataList1, SizeList1} = binary_to_data2( DataList, SizeList, Atom),
- binary_to_data1(Rest, DataList1, SizeList1);
- binary_to_data1(<<?STRING_EXT, Len:16, Bin:Len/binary, Rest/binary>>, DataList, SizeList) ->
- String = binary_to_list(Bin),
- %%msg(string, String),
- {DataList1, SizeList1} = binary_to_data2( DataList, SizeList, String),
- binary_to_data1(Rest, DataList1, SizeList1);
- binary_to_data1(<<?BINARY_EXT, Len:32, Bin:Len/binary, Rest/binary>>, DataList, SizeList) ->
- %%msg(binary, Bin),
- {DataList1, SizeList1} = binary_to_data2( DataList, SizeList, Bin),
- binary_to_data1(Rest, DataList1, SizeList1);
- binary_to_data1(<<?LIST_EXT, ElemtSize:32, Bin/binary>>, DataList, SizeList) ->
- %%msg(list, Bin),
- binary_to_data1(Bin, DataList, [{list, ElemtSize+1, 0}|SizeList]);
- binary_to_data1(<<?NIL_EXT, Rest/binary>>, DataList, SizeList) ->
- %%msg(list_nil, []),
- {DataList1, SizeList1} = binary_to_data2( DataList, SizeList, []),
- binary_to_data1(Rest, DataList1, SizeList1);
- binary_to_data1(<<>>, DataList, _SizeList) ->
- %%msg(final, DataList),
- case lists:reverse(DataList) of
- [Data] -> next;
- [] -> Data=error;
- Data -> next
- end,
- Data;
- binary_to_data1(Bin, _DataList, _SizeList) ->
- msg(unknown, Bin),
- error.
- gen_small_big(<<Bin/binary>>) ->
- gen_small_big(Bin, 0, 0).
- gen_small_big(<<>>, Number, Index) ->
- {Index, Number};
- gen_small_big(<<Num:8, Rest/binary>>, Number, Index) ->
- gen_small_big(Rest, Number + Num * (1 bsl (Index * 8)), Index+1).
- msg(Type, Data) ->
- io:format("~w ~w~n", [Type,Data]),
- ok.
- 16> c(test).
- {ok,test}
- 17> test:term_to_data({a,b,c}).
- {a,b,c}
- 18> test:term_to_data([]).
- []
- 19> test:term_to_data({a,b,{c,{d,{e,"TTT"}},f,[g,h,i],[j]}}).
- {a,b,{c,{d,{e,"TTT"}},f,[g,h,i],[j]}}