以块为单位拆分二进制文件的更好方法,最好是使用位串理解

时间:2011-05-04 08:33:25

标签: erlang list-comprehension bitstring

我正在尝试用更优雅的东西替换以下功能:

split_packet(_, <<>>) ->
    [];
split_packet(Size, P) when byte_size(P) < Size ->
    [ P ];
split_packet(Size, P) ->
    {Chunk, Rest} = split_binary(P, Size),
    [ Chunk | split_packet(Size, Rest) ].

(我现在这不是尾递归 - 想要保持简单,除了在新的Erlang版本中性能明智无关)

示例输出:

1> split_packet(3, <<1,2,3,4,5,6,7,8>>).
[<<1,2,3>>,<<4,5,6>>,<<7,8>>]

具有列表推导的优雅解决方案将是更可取的,因为其结果将通过列表理解进一步处理,然后可以将其包含在一个理解中。

我试过

[ X || <<X:Size/binary>> <= P ].

但如果Size不是byte_site(P)的倍数:

,则会丢弃最后一个块
2>  [ X || <<X:3/binary>> <= <<1,2,3,4,5,6,7,8>> ].
[<<1,2,3>>,<<4,5,6>>]

3 个答案:

答案 0 :(得分:4)

坦率地说,我对你当前的版本没有太大的错误。正如您所述,您无法使用二进制/列表解析来执行此操作,因为最后一个片段将被丢弃。

我唯一能想到的是重新排序这些条款以匹配最常见的案例:

split_packet(Size, P) when byte_size(P) >= Size->
    {Chunk, Rest} = split_binary(P, Size),
    [Chunk|split_packet(Size, Rest)];
split_packet(_Size, <<>>) ->
    [];
split_packet(_Size, P)  ->
    [P].

答案 1 :(得分:2)

您可以使用(Size - (byte_size(Binary) rem Size)) * 8填充输入二进制文件,通过列表理解[ X || <<X:Size/binary>> <= P ]

运行它

Y = (Size - (byte_size(Binary) rem Size)) * 8

[ X || << X:3/binary >> <= << Binary/binary , 0:Y >> ]

然后从最后一段中删除额外的位..

答案 2 :(得分:2)

原作的变体可能会更有效:

split_packet(Size, Data) when Size > 0 ->
    case Data of
        <<Packet:Size/binary, Rest/binary>> ->
            [Packet | split_packet(Size, Rest)];
        <<>> ->
            [];
        _ ->
            [Data]
    end.