我通过查询字符串传递给Erlang BERT。我正在通过带有http_bin选项的gen_tcp读取它,所以它就像这样到达<<“131,104,1,100,0,2,104,105”>>。这几乎是正确的,因为我想用binary_to_term / 2解码它。但是binary_to_term / 2想要二进制二进制,而不是字符串二进制(它想要<<< 131,104,1,100,0,2,104,105>><<<“131,104,1,100,0,2,104,105”>>)
我可以将它解析为正确的形式。
parse(Source) ->
Bins = binary:split(Source, <<",">>, [global]),
parse(Bins, []).
parse([H | T], Acc) ->
parse(T, [list_to_integer(binary_to_list(H)) | Acc]);
parse([], Acc) ->
list_to_binary(lists:reverse(Acc)).
但这似乎很复杂,并且比我希望的要慢(~5k / sec,每个都是200字节)。还提出了一些基于io_lib的东西:fread / 2,但它并没有好多少,看起来仍然很尴尬。
在某处可能有BIF或NIF吗?
如果没有,是否有更好的方法来加快上述速度?
答案 0 :(得分:0)
对于它的价值,一个替代解决方案 - 可能更慢,但可能更少临时,取决于品味 - 是将其视为解析Erlang子集的问题,对于哪些工具存在:
parse(Source) ->
case erl_scan:string(Source++" .") of
{ok, Tokens, _} ->
case erl_parse:parse_term(Tokens) of
{ok, Bin} when is_binary(Bin) -> % Only accept binary literals.
Bin;
_ -> error(badarg)
end;
_ -> error(badarg)
end.
在这种情况下可能有点过分,但没有比原始解决方案更多的代码。
答案 1 :(得分:0)
使用此代码,您可以使用本机(HiPE)解析高达75MB / s,使用字节代码解析高达17MB / s:
-module(str_to_bin).
-export([str_to_bin/1]).
str_to_bin(Bin) when is_binary(Bin) ->
str_to_bin(Bin, <<>>).
-define(D(X), X >= $0, X =< $9 ).
-define(C(X), (X band 2#1111)).
str_to_bin(<<X,Y,Z,Rest/binary>>, Acc)
when ?D(X), ?D(Y), ?D(Z) ->
str_to_bin_(Rest, <<Acc/binary, (?C(X)*100 + ?C(Y)*10 + ?C(Z))>>);
str_to_bin(<<Y,Z,Rest/binary>>, Acc)
when ?D(Y), ?D(Z) ->
str_to_bin_(Rest, <<Acc/binary, (?C(Y)*10 + ?C(Z))>>);
str_to_bin(<<Z,Rest/binary>>, Acc)
when ?D(Z) ->
str_to_bin_(Rest, <<Acc/binary, ?C(Z)>>).
-compile({inline, [str_to_bin_/2]}).
str_to_bin_(<<>>, Acc) -> Acc;
str_to_bin_(<<$,, Rest/binary>>, Acc) -> str_to_bin(Rest, Acc).