Wie kann ich einen NodeJS-Binärpuffer in einen JavaScript-ArrayBuffer konvertieren?
javascript
node.js
binary
buffer
arraybuffer
Drake Amara
quelle
quelle
Array
. Um also viele Floats zu speichern, benötigenFloat32Array
Sie 4 Bytes. Und wenn Sie eine schnelle Serialisierung dieser Floats in eine Datei wünschen, benötigen Sie eineBuffer
, da die Serialisierung in JSON ewig dauert.Antworten:
Instanzen von
Buffer
sind auch Instanzen vonUint8Array
in node.js 4.x und höher. Die effizienteste Lösung ist daher derbuf.buffer
direkte Zugriff auf die Eigenschaft gemäß https://stackoverflow.com/a/31394257/1375574 . Der Buffer-Konstruktor verwendet auch ein ArrayBufferView-Argument, wenn Sie in die andere Richtung gehen müssen.Beachten Sie, dass dadurch keine Kopie erstellt wird. Dies bedeutet, dass beim Schreiben in eine ArrayBufferView in die ursprüngliche Buffer-Instanz geschrieben wird.
In älteren Versionen hat node.js beide ArrayBuffer als Teil von v8, aber die Buffer-Klasse bietet eine flexiblere API. Zum Lesen oder Schreiben in einen ArrayBuffer müssen Sie nur eine Ansicht erstellen und kopieren.
Vom Puffer zum ArrayBuffer:
Von ArrayBuffer zu Buffer:
quelle
size&0xfffffffe
32-Bit-Ganzzahlen kopieren, dann, wenn noch 1 Byte übrig ist, 8-Bit-Ganzzahl kopieren, wenn 2 Byte, 16-Bit-Ganzzahl kopieren, und wenn 3 Byte, 16-Bit- und 8-Bit-Ganzzahl kopieren.ab
zurückgegeben? Es ist nichts damit gemachtab
? Ich bekomme immer{}
als Ergebnis.slice()
Methode gibt eine neue zurück,ArrayBuffer
deren Inhalt eine Kopie dieserArrayBuffer
Bytes von Anfang, einschließlich, bis Ende, exklusiv ist.' - MDNArrayBuffer.prototype.slice()
Keine Abhängigkeiten, am schnellsten, Node.js 4.x und höher
Buffer
s sindUint8Array
s, Sie müssen also nur den Bereich des Hintergrunds in Scheiben schneiden (kopieren)ArrayBuffer
.Das
slice
und Offset-Material ist erforderlich, da kleineBuffer
s (standardmäßig weniger als 4 kB, die Hälfte der Poolgröße ) Ansichten auf einer gemeinsam genutzten Datei sein könnenArrayBuffer
. Ohne Slicing können SieArrayBuffer
Daten von einem anderen erhaltenBuffer
. Siehe Erklärung in den Dokumenten .Wenn Sie letztendlich eine benötigen
TypedArray
, können Sie eine erstellen, ohne die Daten zu kopieren:Keine Abhängigkeiten, mäßige Geschwindigkeit, jede Version von Node.js.
Verwenden Sie die Antwort von Martin Thomson , die in O (n) Zeit ausgeführt wird. (Siehe auch meine Antworten auf Kommentare zu seiner Antwort zu Nichtoptimierungen. Die Verwendung einer DataView ist langsam. Selbst wenn Sie Bytes umdrehen müssen, gibt es schnellere Möglichkeiten.)
Abhängigkeit, schnell, Node.js ≤ 0,12 oder iojs 3.x.
Sie können https://www.npmjs.com/package/memcpy verwenden , um in beide Richtungen zu gelangen (Buffer to ArrayBuffer und zurück). Es ist schneller als die anderen hier veröffentlichten Antworten und eine gut geschriebene Bibliothek. Knoten 0.12 bis iojs 3.x erfordern die Gabel von ngossen (siehe hier ).
quelle
.byteLength
und.byteOffset
dokumentiert?var ab = b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength);
hat meinen Tag gerettet"Von ArrayBuffer zu Puffer" könnte folgendermaßen erfolgen:
quelle
Ein schnellerer Weg, um es zu schreiben
Dies scheint jedoch ungefähr viermal langsamer zu laufen als die vorgeschlagene Funktion toArrayBuffer für einen Puffer mit 1024 Elementen.
quelle
Buffer
auch Instanzen vonUint8Array
in Node.js 4.x und höher sind. Für niedrigere Node.js-Versionen müssen Sie einetoArrayBuffer
Funktion implementieren .1. A.
Buffer
ist nur eine Ansicht zum Betrachten einesArrayBuffer
.A
📜Buffer
ist in der Tat einFastBuffer
, dasextends
(erbt von)Uint8Array
, was eine Oktetteinheit ist Ansicht ( „partial Accessor“) des Ist - Speicher, eineArrayBuffer
./lib/buffer.js#L65-L73
Node.js 9.4.02. Die Größe eines
ArrayBuffer
und die Größe seiner Ansicht können variieren.Grund Nr. 1:
Buffer.from(arrayBuffer[, byteOffset[, length]])
.Mit
Buffer.from(arrayBuffer[, byteOffset[, length]])
können Sie einBuffer
mit Angabe des Basiswerts erstellenArrayBuffer
sowie der Position und Größe der Ansicht .Grund Nr. 2:
FastBuffer
Speicherzuordnung.Der Speicher wird je nach Größe auf zwei verschiedene Arten zugewiesen.
ArrayBuffer
Speicher , der genau zum erforderlichen Speicher passt./lib/buffer.js#L306-L320
📜 Node.js 9.4.0/lib/buffer.js#L98-L100
Was meinst du mit einem „ Speicherpool "?
Ein Speicherpool ist ein vorab zugewiesener Speicherblock mit fester Größe , um kleine Speicherblöcke für
Buffer
s aufzubewahren . Durch die Verwendung werden die kleinen Speicherblöcke eng zusammengehalten, wodurch dies verhindert wird Fragmentierung die durch die separate Verwaltung (Zuweisung und Freigabe) kleiner Speicherblöcke verursacht wird.In diesem Fall handelt es sich bei den Speicherpools um
ArrayBuffer
s, deren Größe standardmäßig 8 KB beträgtBuffer.poolSize
. Dies ist in angegeben . Wenn ein kleiner Speicherblock für aBuffer
bereitgestellt werden soll, wird geprüft, ob der letzte Speicherpool über genügend verfügbaren Speicher verfügt, um dies zu handhaben. In diesem Fall wird ein Element erstelltBuffer
, das den angegebenen Teil des Speicherpools "anzeigt". Andernfalls wird ein neuer Speicherpool erstellt und so weiter.Sie können auf den Basiswert
ArrayBuffer
von a zugreifenBuffer
. DieBuffer
‚s -buffer
Eigenschaft (das heißt, geerbt vonUint8Array
) hält. Eine „kleine“Buffer
‚s -buffer
Eigenschaft ist eineArrayBuffer
, die den gesamten Speicher - Pool darstellt. In diesem Fall variiert dasArrayBuffer
und dasBuffer
in der Größe.3. Wir müssen also den Speicher extrahieren, den es " ansieht ".
An
ArrayBuffer
hat eine feste Größe, daher müssen wir es herausziehen, indem wir eine Kopie des Teils erstellen. Dazu verwenden wirBuffer
‚sbyteOffset
Eigentum undlength
Immobilien , die von vererbt werdenUint8Array
, und dasArrayBuffer.prototype.slice
Verfahren , das eine Kopie eines Teils eines machtArrayBuffer
. Die hier beschriebeneslice()
-ing-Methode wurde von @ZachB inspiriert .4. Leistungsverbesserung
Wenn Sie die Ergebnisse schreibgeschützt verwenden oder den
Buffer
Inhalt der Eingabe ändern möchten , können Sie unnötiges Kopieren des Speichers vermeiden.quelle
obtain_arraybuffer
:buf.buffer.subarray
scheint nicht zu existieren. Meinten Siebuf.buffer.slice
hier?ArrayBuffer.prototype.slice
und später geändertUint8Array.prototype.subarray
. Oh, und ich habe es falsch gemacht. Wahrscheinlich war ich damals etwas verwirrt. Dank dir ist jetzt alles gut.Verwenden Sie das folgende ausgezeichnete npm-Paket :
to-arraybuffer
.Oder Sie können es selbst implementieren. Wenn Ihr Puffer aufgerufen wird
buf
, gehen Sie folgendermaßen vor:quelle
Sie können sich eine
ArrayBuffer
als getippt vorstellenBuffer
.Ein benötigt
ArrayBuffer
daher immer einen Typ (die sogenannte "Array Buffer View"). In der Regel hat die Array-Pufferansicht den TypUint8Array
oderUint16Array
.Es gibt einen guten Artikel von Renato Mangini über die Konvertierung zwischen einem ArrayBuffer und einem String .
Ich habe die wesentlichen Teile in einem Codebeispiel (für Node.js) zusammengefasst. Es wird auch gezeigt, wie zwischen typisiert
ArrayBuffer
und untypisiert konvertiert wirdBuffer
.quelle
Ich habe das oben für ein Float64Array ausprobiert und es hat einfach nicht funktioniert.
Am Ende wurde mir klar, dass die Daten wirklich in korrekten Blöcken in die Ansicht gelesen werden mussten. Dies bedeutet, dass jeweils 8 Bytes aus dem Quellpuffer gelesen werden.
Jedenfalls ist es das, was ich am Ende hatte ...
quelle
Buffer.read*
Methoden sind auch alle langsam.Dieser Proxy macht den Puffer als eines der TypedArrays ohne Kopie verfügbar. ::
https://www.npmjs.com/package/node-buffer-as-typedarray
Es funktioniert nur mit LE, kann aber problemlos auf BE portiert werden. Außerdem musste ich nie testen, wie effizient dies ist.
quelle
Jetzt gibt es dafür ein sehr nützliches npm-Paket:
buffer
https://github.com/feross/bufferEs wird versucht, eine API bereitzustellen, die zu 100% mit der Puffer-API des Knotens identisch ist, und Folgendes zuzulassen:
und einige mehr.
quelle
NodeJS hatte zu einem bestimmten Zeitpunkt (ich glaube es war v0.6.x) ArrayBuffer-Unterstützung. Ich habe eine kleine Bibliothek für Base64 - Codierung und Decodierung hier , sondern auf v0.7 seit der Aktualisierung die Tests (auf NodeJS) scheitern. Ich denke darüber nach, etwas zu schaffen, das dies normalisiert, aber bis dahin
Buffer
sollte wohl Node's Native verwendet werden.quelle
Ich habe meinen Knoten bereits auf Version 5.0.0 aktualisiert und arbeite damit:
Ich benutze es, um mein VHD-Image zu überprüfen.
quelle
toArrayBuffer(new Buffer([1,2,3]))
->['01', '02', '03']
- Dies gibt ein Array von Zeichenfolgen zurück, keine Ganzzahlen / Bytes.