我正在创建一个需要解析来自第三方程序的二进制TCP流的Erlang应用程序。 我可以接收的其中一种数据包的格式如下:
N_terms * [标志(8位),类型(8位),[可选数据]]。
我遇到的问题是可选数据是由所有可能的排列决定的 标志和类型的组合。此外,根据类型,还有与之关联的其他可选数据。
如果我用命令式语言编写解析器,我只需读取2个字段,然后有一系列if(...)语句,我将读取一个值并增加我在流中的位置。在Erlang中,我最初的天真假设是我会有2 ^ N个函数子句来匹配流上的字节语法,其中N是标志的总数+所有带有附加可选数据的类型。
就目前而言,我至少有3个标志和1个类型,其中包含我必须实现的可选数据,这意味着我将在流上匹配16个不同的函数子句。
在Erlang中必须有更好的,惯用的方法 - 我缺少什么?
编辑: 我应该澄清我事先不知道条款的数量。
答案 0 :(得分:4)
一种解决方案是采取
<<Flag:8/integer, Type:8/integer, Rest/binary>>
然后编写一个函数decode(Flag, Type)
,它返回Rest
将包含的描述。现在,该描述可以传递给Rest
的解码器,然后可以使用给出的描述来正确地解析它。一个简单的解决方案是将描述放入列表中,每当您从流中解码某些内容时,您都可以使用该描述列表来检查它是否有效。也就是说,描述就像你的构造一样。
对于指针移动,很容易。如果您有Binary
并对其进行解码
<<Take:N/binary, Next/binary>> = Binary,
接下来是您正在搜索的引擎盖下移动的指针。所以你可以将你的二进制文件分成几部分,以获得下一部分的工作。
答案 1 :(得分:1)
我会解析它:
parse_term(Acc,0,<<>>) -> {ok,Acc};
parse_term(_,0,_) -> {error,garbage};
parse_term(Acc,N,<<Flag:8/integer,Type:8/integer,Rest/binary>>) ->
{Optional,Rest1} = extract_optional(Flag,Type,Rest),
parse_term([{Flag,Type,Optional}|Acc],N-1,Rest1>>).
parse_stream(<<NTerms/integer,Rest/binary>>)->
parse_term([],NTerms,Rest).