- 浏览: 87406 次
文章分类
最新评论
erlang语言实现binary_to_term
前言
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}可以看出term_to_binary/1生成的二进制数据是比较有规律的,第1个字节固定是131,遵循着一定的封包格式,数据才能被解析出来。知道这个二进制数据的组织形式,就可以用任意语言解包Erlang数据。
初识binary数据
erlang长整形
10.18 SMALL_BIG_EXT
Bignums are stored in unary form with aSignbyte 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 byLennumbers of 8 bit Latin1 characters that forms theAtomName.Note: The maximum allowed value forLenis 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
Lengthis the number of elements that follows in theElementssection.Tailis the final tail of the list; it isNIL_EXTfor 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.保存为test.erl,运行结果如下:
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.保存为test.erl,运行结果如下:
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]}}
相关推荐
erlang提供了binary_to_term 函数,用于把二进制数据转为原始的erlang数据。这个函数都是c实现的,这里用erlang语言实现了,很有参考价值,其他语言可以参考这个解析erlang二进制协议数据。配套文章地址...
有些同学想把Erlang数据通过term_to_binary函数封包后以二制进形式存入数据库,然后用PHP读取并解包成PHP数组。 为了解决上面的这种应用场合中遇到的问题, 参考peb(Php-Erlang Bridge)扩展写了这个类似erlang:...
标题中的“<27>erlang record”可能指的是Erlang编程语言中的Record特性,它是一种数据结构,类似于结构体或者哈希表,用于组织和操作数据。在Erlang中,Record提供了一种方便的方式来定义和访问具有固定字段的数据...
Erlang是一种面向并发的、函数式编程语言,被广泛应用于分布式系统和高容错环境。在Erlang中,术语(term)是其数据结构的基础,它包含了各种不同的数据类型,如原子(atom)、整数、浮点数、列表、元组、二进制、...
gen_tcp:send(Socket, term_to_binary(Reply)), loop(Socket); {tcp_closed, Socket} -> io:format("Server socket closed~n") end. ``` 在上述代码中,服务器设置为监听端口1234,所有数据都以二进制格式发送...
后者是通常:erlang.term_to_binary / 1真正难以解决的问题,通常是为了防止在节点之间传输包含大列表/列表/地图/元组的消息。 Pack通过使用支持形状重复的模式+数据缓冲区方法(例如“ N *两个整数的整数”)并...
总结,clojure-erlastic是连接Clojure与Erlang的桥梁,通过BERT编码和core.async通道实现跨语言的高效通信,为开发者提供了一种新的方式来利用Erlang的强大功能,同时保持Clojure的编程体验。对于那些希望在两个世界...
此外,Erlang中还提供了二进制到Erlang数据类型的转换函数,例如`term_to_binary/1`和`binary_to_term/1`,用于二进制数据和Erlang数据之间的转换。 Erlang语言在设计时就考虑到了和C语言的互操作性。通过精心选择...
ETFs是一种基于Erlang的外部术语格式(即erlang:term_to_binary/1 )的简单的可流式二进制序列化容器格式。 用法 ETFs的公共接口是ETFs.stream!/1 。 ETFs.stream! 从Enumerable和Collectable的意义上讲,它生成的...
4. **处理结果**:`luerl:eval/2`和`luerl:call/3`会返回一个包含执行结果的Erlang二进制对象,可以通过`luerl:binary_to_term/1`将其转换为Erlang术语。 5. **错误处理**:如果Lua代码中发生错误,luerl会抛出一个...
在Binary Erlang Term和javascript类型之间进行解码和编码 通过nodeJS可读和可写(双工)创建一个简单的Erlang端口接口 创建一个“ gen_server样式”处理程序来管理您的端口 用法示例 在详细介绍之前,让我们以一个...
ERNIE,全称为“Effective and Reliable Notation for Interchange of Erlang”,是一种高效的数据二进制编码格式,基于Erlang的外部条款格式(External Term Format, ETF)。它旨在为跨语言通信提供一种标准化的...
Erlang 二进制术语(Erlang Binary Term Format)是 Erlang 语言中用于序列化和反序列化的标准格式,通常用于进程间通信(IPC)和网络通信。FsServer 使用这种格式,使得它能够与 Erlang 系统或支持该协议的其他系统...
ETS(Erlang Term Storage)是内存中的表存储,而 Mnesia 是分布式数据库系统,两者都提供高效的数据存储: ```elixir table = :ets.new(:my_table, [:set, :public, :named_table]) :ets.insert(table, {key, ...
如果您来自 Erlang 背景,您可能甚至不知道解析器组合库是什么。 我们从核心数据类型开始 - type parser () :: fun (( binary ()) -> { ok , { term (), integer (), binary ()}} | { error , { term (), integer ...
BERT(Binary ERlang Term)是一种数据序列化格式,最初由Erlang编程语言社区开发,用于高效地在网络上传输和存储数据。BERT.js是这个概念的一个实现,它将BERT支持带入了JavaScript环境中,特别是在客户端...
BERT 是 Ruby 的 BERT (Binary ERlang Term) 序列化库,可以编码 Ruby 对象到 BERT 格式,或者解码 BERT 二进制到 Ruby 对象。BERT 规范请看 bert-rpc.org。以下的 Ruby 类实例会被自动转化为简单的 BERT 类型:...