将二进制文件分割成块的更好方法,最好使用位串理解

Pee*_*ger 2 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) ].
Run Code Online (Sandbox Code Playgroud)

(我现在这不是尾递归——想要保持简单,此外在新的 Erlang 版本中性能并不重要)

输出示例:

1> split_packet(3, <<1,2,3,4,5,6,7,8>>).
[<<1,2,3>>,<<4,5,6>>,<<7,8>>]
Run Code Online (Sandbox Code Playgroud)

具有列表推导式的优雅解决方案将是更好的选择,因为其结果将使用列表推导式进一步处理,然后可以将其包装在一个推导式中。

我试过

[ X || <<X:Size/binary>> <= P ].
Run Code Online (Sandbox Code Playgroud)

但如果 Size 不是以下的倍数,则会忽略最后一个块byte_site(P)

2>  [ X || <<X:3/binary>> <= <<1,2,3,4,5,6,7,8>> ].
[<<1,2,3>>,<<4,5,6>>]
Run Code Online (Sandbox Code Playgroud)

Ada*_*erg 5

坦率地说,我认为您当前的版本没有太大问题。正如您所说,您无法使用二进制/列表理解来做到这一点,因为最后一个片段将被丢弃。

我唯一能想到的就是重新排序子句以首先匹配最常见的情况:

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].
Run Code Online (Sandbox Code Playgroud)