Лучший способ разбить двоичный файл на куски, предпочтительно с пониманием битовых строк


Я пытаюсь заменить следующую функцию чем-то более элегантным:

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>>]
Изящное решение со списком постижений было бы предпочтительнее, так как результат этого далее обрабатывается с помощью списка-понимания, которое затем может быть обернуто в одно понимание.

I пробовал

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

Но это оставляет последний кусок, если размер не кратен byte_site(P):

2>  [ X || <<X:3/binary>> <= <<1,2,3,4,5,6,7,8>> ].
[<<1,2,3>>,<<4,5,6>>]
3 2

3 ответа:

Честно говоря, я не вижу ничего плохого в вашей нынешней версии. Как вы утверждаете, вы не можете сделать это с двоичным пониманием/списком, потому что последний фрагмент будет отброшен.

Единственное, что я могу придумать, это переупорядочить предложения, чтобы сначала они соответствовали наиболее частому случаю:

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].

Возможно, вы могли бы заполнить входной двоичный файл (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 >> ]

А затем отрежьте лишние биты от последнего сегмента..

Вариант вашего оригинала, который может быть немного более эффективным:

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