55 Stimmen

Wie kann ich zwei Binärdateien in Erlang verketten?

Wie kann ich zwei Binärdateien in Erlang verketten?

Nehmen wir zum Beispiel an, ich habe:

B1 = <<1,2>>.
B2 = <<3,4>>.

Wie verkette ich B1 und B2, um ein binäres B3 zu erzeugen, das <<1,2,3,4>> ist?

Der Grund, warum ich das frage, ist, dass ich Code schreibe, um ein Paket für ein Netzwerkprotokoll zu kodieren. Ich implementiere dies, indem ich Kodierer für die Felder im Paket schreibe, und ich muss diese Felder verketten, um das gesamte Paket zu erstellen.

Vielleicht mache ich das falsch. Sollte ich das Paket als eine Liste von Ganzzahlen aufbauen und die Liste im letzten Moment in ein Binärformat umwandeln?

131voto

28> B1= <<1,2>>.
<<1,2>>
29> B2= <<3,4>>.
<<3,4>>
30> B3= <<B1/binary, B2/binary>>.
<<1,2,3,4>>
31>

0 Stimmen

Vermutlich ist dies keine O(1)-Operation, so dass es immer noch Sinn machen würde, eine tiefe Liste (IO-Liste) zu erstellen, wie von cthulahoops vorgeschlagen, und das Durchlaufen der tiefen Liste zu verschieben, bis ich bereit bin, das Paket zu senden?

18 Stimmen

Beide Antworten sind gut. io_list Strukturen aus cthulahoops sind ideal für i/o; aber da dies nun der Top-Google-Treffer für "erlang concatenate binaries" ist, ist es schön, die streng korrekte Antwort auch hier zu haben.

41voto

cthulahoops Punkte 3755

Sie können Binärdateien mit der Bit-Syntax verketten:

1> B1 = <<1,2>>.
<<1,2>>
2> B2 = <<3,4>>.
<<3,4>>
3> B3 = <<B1/binary, B2/binary>>.
<<1,2,3,4>>

In vielen Fällen, insbesondere wenn die Daten für das Netz bestimmt sind, kann man die Verkettung vermeiden, indem man stattdessen eine io_list konstruiert.

B3 = [B1, B2],
gen_tcp:send(Socket, B3).

Dies ist O(1), da keine der beiden Binärdateien kopiert werden muss. gen_tcp:send akzeptiert die tiefe Liste und geht die Struktur für die Ausgabe durch. (Eine Liste mit zwei Elementen benötigt nur sehr wenig zusätzlichen Speicher, so dass der Speicher-Overhead gering ist).

In einigen Fällen (wiederholte Anhänge an dieselbe Binärdatei) verfügt Erlang jetzt über Optimierungen, die das Kopieren der Binärdatei, an die angehängt wird, vermeiden, so dass die Verwendung von io_lists weniger relevant sein kann: http://erlang.org/doc/efficiency_guide/binaryhandling.html#constructing-binaries


Historische Anmerkung: Ursprünglich habe ich nur die io_list-Lösung empfohlen, und viele Kommentatoren haben zu Recht darauf hingewiesen, dass ich die Frage nicht beantwortet habe. Hoffentlich ist die akzeptierte Antwort jetzt vollständig. (11 Jahre später!)

0 Stimmen

Danke! Ich war nicht vertraut mit den Konzepten der tiefen Listen und io-Listen in Erlang.

25 Stimmen

Ich glaube nicht, dass dieser Code richtig ist. Er gibt zurück: [<<1,2>>,<<3,4>>] und das ist nicht das, worum @Cayle Spandon gebeten hat. Die Antwort ist also falsch.

5 Stimmen

@Worker - die Antwort, die cthulahoops gegeben hat, zielt nicht darauf ab, die beiden Binärdateien tatsächlich zu verketten. Der Sinn dieser Antwort ist, dass Sie den Rechenaufwand für die Verkettung der beiden Binärdateien von vornherein vermeiden können, wenn der Code, mit dem Sie arbeiten, iolists akzeptiert. Da der ursprüngliche Fragesteller sagte, dass er versucht, ein Netzwerkpaket zu erstellen, deutet diese Antwort darauf hin, dass die Verkettung der beiden Binärdateien vielleicht nicht wirklich der beste Weg ist, um das zu erreichen, was der ursprüngliche Fragesteller braucht.

22voto

David N. Welton Punkte 1865

Um eine io_list zu verwenden, könnten Sie dies tun:

erlang:iolist_to_binary([<<"foo">>, <<"bar">>])

Das ist schön und gut lesbar. Man könnte auch Listen und andere Dinge darin verwenden, wenn das praktischer ist.

13voto

pommonico Punkte 471

Um auf die letzte Antwort aufzubauen:

bjoin(List) ->
    F = fun(A, B) -> <<A/binary, B/binary>> end,
    lists:foldr(F, <<>>, List).

8voto

Logan Capaldo Punkte 38523

Verwenden Sie die Erlang-Funktion list_to_binary(List). Die Dokumentation finden Sie hier: http://www.erlang.org/documentation/doc-5.4.13/lib/kernel-2.10.13/doc/html/erlang.html#list_to_binary/1

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X