Konvertieren Sie einen binären NodeJS-Puffer in einen JavaScript-ArrayBuffer

Lesezeit: 11 Minuten

Konvertieren Sie einen binaren NodeJS Puffer in einen JavaScript ArrayBuffer
Drake Amara

Wie kann ich einen NodeJS-Binärpuffer in einen JavaScript-ArrayBuffer konvertieren?

  • Mich würde interessieren warum man das machen muss?

    – Chris Biscardi

    23. Dezember 2011 um 2:46 Uhr

  • Ein gutes Beispiel wäre das Schreiben einer Bibliothek, die mit Dateien in Browsern und auch für NodeJS-Dateien funktioniert?

    – fbstj

    18. Januar 2012 um 18:36 Uhr

  • oder mit einer Browserbibliothek in NodeJS

    – Orangenhund

    20. Juni 2013 um 15:43 Uhr

  • Ein weiterer Grund ist, dass ein Float zu viele Bytes RAM benötigt, wenn es in einem gespeichert wird Array. Um also viele Schwimmer zu speichern, die Sie benötigen Float32Array wo es 4 Bytes dauert. Und wenn Sie diese Floats schnell in eine Datei serialisieren möchten, benötigen Sie eine Bufferda die Serialisierung zu JSON Ewigkeiten dauert.

    – nponeccop

    13. November 2013 um 13:32 Uhr


  • const file = fs.readFileSync(filePath);also wie benutze ich das? … 30 Minuten später, wow, ich vermisse C.

    – Wilhelm Entriken

    27. Mai 2020 um 4:02 Uhr

Konvertieren Sie einen binaren NodeJS Puffer in einen JavaScript ArrayBuffer
Martin Thompson

Instanzen von Buffer sind auch Fälle von Uint8Array in node.js 4.x und höher. Daher ist die effizienteste Lösung der Zugriff auf die buf.buffer Eigenschaft direkt, gemäß https://stackoverflow.com/a/31394257/1375574. Der Buffer-Konstruktor akzeptiert auch ein ArrayBufferView-Argument, wenn Sie in die andere Richtung gehen müssen.

Beachten Sie, dass dadurch keine Kopie erstellt wird, was bedeutet, dass Schreibvorgänge in eine beliebige ArrayBufferView in die ursprüngliche Buffer-Instanz durchschreiben.


In älteren Versionen hat node.js sowohl ArrayBuffer als Teil von v8, aber die Buffer-Klasse bietet eine flexiblere API. Um einen ArrayBuffer zu lesen oder zu schreiben, müssen Sie nur eine Ansicht erstellen und hinüber kopieren.

Von Buffer zu ArrayBuffer:

function toArrayBuffer(buf) {
    const ab = new ArrayBuffer(buf.length);
    const view = new Uint8Array(ab);
    for (let i = 0; i < buf.length; ++i) {
        view[i] = buf[i];
    }
    return ab;
}

Von ArrayBuffer zu Buffer:

function toBuffer(ab) {
    const buf = Buffer.alloc(ab.byteLength);
    const view = new Uint8Array(ab);
    for (let i = 0; i < buf.length; ++i) {
        buf[i] = view[i];
    }
    return buf;
}

  • Ich würde Ihnen auch empfehlen, dies zu optimieren, indem Sie nach Möglichkeit Ganzzahlen mit DataView kopieren. Noch bis size&0xfffffffekopieren Sie 32-Bit-Ganzzahlen, kopieren Sie dann, wenn 1 Byte übrig ist, 8-Bit-Ganzzahlen, kopieren Sie 16-Bit-Ganzzahlen, wenn 2 Bytes vorhanden sind, und kopieren Sie 16-Bit- und 8-Bit-Ganzzahlen, wenn 3 Bytes übrig sind.

    – Triang3l

    13. Februar 2013 um 17:25 Uhr


  • Siehe die Antwort von kraag22 für eine einfachere Implementierung der Hälfte davon.

    – Orangenhund

    20. Juni 2013 um 16:47 Uhr

  • Habe Buffer -> ArrayBuffer mit einem für den Browser gedachten Modul getestet und es funktioniert hervorragend. Danke!

    – evtl

    26. Mai 2014 um 2:49 Uhr

  • Warum ist ab ist zurückgekommen? Es wird nichts damit gemacht ab? Ich bekomme immer {} als Ergebnis.

    – Andi Giga

    7. Juli 2016 um 15:09 Uhr

  • ‘Die slice() Methode gibt eine neue zurück ArrayBuffer dessen Inhalt eine Kopie davon ist ArrayBuffer‘s Bytes von Anfang, inklusive, bis Ende, exklusiv.’MDN ArrayBuffer.prototype.slice()

    – Константин Ван

    23. Januar 2018 um 19:01 Uhr


1645704912 459 Konvertieren Sie einen binaren NodeJS Puffer in einen JavaScript ArrayBuffer
ZachB

Keine Abhängigkeiten, am schnellsten, Node.js 4.x und höher

Buffers sind Uint8Arrays, also müssen Sie nur seinen Bereich des Trägers schneiden (kopieren). ArrayBuffer.

// Original Buffer
let b = Buffer.alloc(512);
// Slice (copy) its segment of the underlying ArrayBuffer
let ab = b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength);

Die slice und Offset-Zeug ist erforderlich weil klein Buffers (standardmäßig weniger als 4 kB, die Hälfte der Pool Größe) können Ansichten auf einem Shared sein ArrayBuffer. Ohne Aufschneiden können Sie mit einem enden ArrayBuffer Daten von einem anderen enthalten Buffer. Sehen Erklärung in den Dokumenten.

Wenn Sie letztendlich eine benötigen TypedArraykönnen Sie eine erstellen, ohne die Daten zu kopieren:

// Create a new view of the ArrayBuffer without copying
let ui32 = new Uint32Array(b.buffer, b.byteOffset, b.byteLength / Uint32Array.BYTES_PER_ELEMENT);

Keine Abhängigkeiten, moderate Geschwindigkeit, jede Version von Node.js

Verwenden Sie die Antwort von Martin Thomson, die einfließt An) Zeit. (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, dies zu tun.)

Abhängigkeit, schnell, Node.js ≤ 0.12 oder iojs 3.x

Sie können verwenden https://www.npmjs.com/package/memcpy um in beide Richtungen zu gehen (Puffer zu ArrayBuffer und zurück). Es ist schneller als die anderen hier geposteten Antworten und eine gut geschriebene Bibliothek. Node 0.12 bis iojs 3.x erfordern ngossens Fork (siehe Das).

1645704912 296 Konvertieren Sie einen binaren NodeJS Puffer in einen JavaScript ArrayBuffer
kraag22

“From ArrayBuffer to Buffer” könnte auf diese Weise erfolgen:

var buffer = Buffer.from( new Uint8Array(ab) );

  • Das ist das Gegenteil von dem, was OP wollte.

    – Alexander Gontschi

    22. April 2016 um 12:33 Uhr

  • Aber das war es, was ich wollte, mein Problem googeln und froh, dass ich die Lösung gefunden habe.

    – Maciej Krawczyk

    22. März 2017 um 16:04 Uhr

Eine schnellere Art, es zu schreiben

var arrayBuffer = new Uint8Array(nodeBuffer).buffer;

Dies scheint jedoch ungefähr viermal langsamer zu laufen als die vorgeschlagene toArrayBuffer-Funktion auf einem Puffer mit 1024 Elementen.

Konvertieren Sie einen binaren NodeJS Puffer in einen JavaScript ArrayBuffer
Константин Ван

1. A Buffer ist nur ein Ansicht für den Blick in ein ArrayBuffer.

EIN Bufferin der Tat ist ein FastBufferwelcher extends (erbt von) Uint8Arraydie eine Oktetteinheit ist Ansicht („partial accessor“) des eigentlichen Speichers, an ArrayBuffer.

📜/lib/buffer.js#L65-L73 Node.js 9.4.0

class FastBuffer extends Uint8Array {
  constructor(arg1, arg2, arg3) {
    super(arg1, arg2, arg3);
  }
}
FastBuffer.prototype.constructor = Buffer;
internalBuffer.FastBuffer = FastBuffer;

Buffer.prototype = FastBuffer.prototype;

2. Die Größe eines ArrayBuffer und die Größe seiner Ansicht variieren.

Grund Nr. 1: Buffer.from(arrayBuffer[, byteOffset[, length]]).

Mit Buffer.from(arrayBuffer[, byteOffset[, length]])können Sie eine erstellen Buffer mit Angabe des Basiswertes ArrayBuffer und die Position und Größe der Ansicht.

const test_buffer = Buffer.from(new ArrayBuffer(50), 40, 10);
console.info(test_buffer.buffer.byteLength); // 50; the size of the memory.
console.info(test_buffer.length); // 10; the size of the view.

Grund Nr. 2: FastBufferSpeicherbelegung von .

Es weist den Speicher je nach Größe auf zwei verschiedene Arten zu.

  • Wenn die Größe weniger als die Hälfte der Größe von a Gedächtnispool und ist nicht 0 („klein“): es nutzt a Gedächtnispool um den erforderlichen Speicher vorzubereiten.
  • Anders: es schafft eine dedizierte ArrayBuffer das passt genau zum benötigten Arbeitsspeicher.

📜/lib/buffer.js#L306-L320 Node.js 9.4.0

function allocate(size) {
  if (size <= 0) {
    return new FastBuffer();
  }
  if (size < (Buffer.poolSize >>> 1)) {
    if (size > (poolSize - poolOffset))
      createPool();
    var b = new FastBuffer(allocPool, poolOffset, size);
    poolOffset += size;
    alignPool();
    return b;
  } else {
    return createUnsafeBuffer(size);
  }
}

📜/lib/buffer.js#L98-L100 Node.js 9.4.0

function createUnsafeBuffer(size) {
  return new FastBuffer(createUnsafeArrayBuffer(size));
}

Was meinst du mit einem „Gedächtnispool?”

EIN Gedächtnispool ist eine feste Größe vorbelegt Speicherblock zum Aufbewahren kleiner Speicherblöcke für BufferS. Die Verwendung hält die kleinen Speicherbrocken eng zusammen, verhindert also Zersplitterung verursacht durch getrennte Verwaltung (Zuweisung und Freigabe) von kleinen Speicherblöcken.

In diesem Fall sind die Speicherpools ArrayBuffers, deren Größe standardmäßig 8 KiB beträgt, was in angegeben ist Buffer.poolSize. Wenn es darum geht, einen kleinen Speicherblock für a bereitzustellen Buffer, es prüft, ob der letzte Speicherpool genügend verfügbaren Speicher hat, um dies zu handhaben; Wenn ja, erstellt es eine Buffer das “Ansichten” den gegebenen Teil des Speicherpools, ansonsten wird ein neuer Speicherpool erstellt und so weiter.


Sie können auf den Basiswert zugreifen ArrayBuffer von a Buffer. Die Buffer‘S buffer Eigentum (d.h. geerbt von Uint8Array) hält es. EIN “klein” Buffer‘S buffer Eigentum ist ein ArrayBuffer die den gesamten Speicherpool darstellt. Also in diesem Fall die ArrayBuffer und das Buffer variiert in der Größe.

const zero_sized_buffer = Buffer.allocUnsafe(0);
const small_buffer = Buffer.from([0xC0, 0xFF, 0xEE]);
const big_buffer = Buffer.allocUnsafe(Buffer.poolSize >>> 1);

// A `Buffer`'s `length` property holds the size, in octets, of the view.
// An `ArrayBuffer`'s `byteLength` property holds the size, in octets, of its data.

console.info(zero_sized_buffer.length); /// 0; the view's size.
console.info(zero_sized_buffer.buffer.byteLength); /// 0; the memory..'s size.
console.info(Buffer.poolSize); /// 8192; a memory pool's size.

console.info(small_buffer.length); /// 3; the view's size.
console.info(small_buffer.buffer.byteLength); /// 8192; the memory pool's size.
console.info(Buffer.poolSize); /// 8192; a memory pool's size.

console.info(big_buffer.length); /// 4096; the view's size.
console.info(big_buffer.buffer.byteLength); /// 4096; the memory's size.
console.info(Buffer.poolSize); /// 8192; a memory pool's size.

3. Also müssen wir den Speicher extrahieren „Ansichten.“

Ein ArrayBuffer hat eine feste Größe, also müssen wir es extrahieren, indem wir eine Kopie des Teils erstellen. Dazu verwenden wir Buffer‘S byteOffset Eigentum und length Eigentumdie vererbt werden Uint8Arrayund der ArrayBuffer.prototype.slice Methodedas eine Kopie eines Teils einer erstellt ArrayBuffer. Die slice()-ing-Methode hierin wurde von @ZachB inspiriert.

const test_buffer = Buffer.from(new ArrayBuffer(10));
const zero_sized_buffer = Buffer.allocUnsafe(0);
const small_buffer = Buffer.from([0xC0, 0xFF, 0xEE]);
const big_buffer = Buffer.allocUnsafe(Buffer.poolSize >>> 1);

function extract_arraybuffer(buf)
{
    // You may use the `byteLength` property instead of the `length` one.
    return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length);
}

// A copy -
const test_arraybuffer = extract_arraybuffer(test_buffer); // of the memory.
const zero_sized_arraybuffer = extract_arraybuffer(zero_sized_buffer); // of the... void.
const small_arraybuffer = extract_arraybuffer(small_buffer); // of the part of the memory.
const big_arraybuffer = extract_arraybuffer(big_buffer); // of the memory.

console.info(test_arraybuffer.byteLength); // 10
console.info(zero_sized_arraybuffer.byteLength); // 0
console.info(small_arraybuffer.byteLength); // 3
console.info(big_arraybuffer.byteLength); // 4096

4. Leistungsverbesserung

Wenn Sie die Ergebnisse schreibgeschützt verwenden möchten, oder es in Ordnung ist, die Eingabe zu ändern Buffers’ Inhaltkönnen Sie unnötiges Kopieren des Speichers vermeiden.

const test_buffer = Buffer.from(new ArrayBuffer(10));
const zero_sized_buffer = Buffer.allocUnsafe(0);
const small_buffer = Buffer.from([0xC0, 0xFF, 0xEE]);
const big_buffer = Buffer.allocUnsafe(Buffer.poolSize >>> 1);

function obtain_arraybuffer(buf)
{
    if(buf.length === buf.buffer.byteLength)
    {
        return buf.buffer;
    } // else:
    // You may use the `byteLength` property instead of the `length` one.
    return buf.subarray(0, buf.length);
}

// Its underlying `ArrayBuffer`.
const test_arraybuffer = obtain_arraybuffer(test_buffer);
// Just a zero-sized `ArrayBuffer`.
const zero_sized_arraybuffer = obtain_arraybuffer(zero_sized_buffer);
// A copy of the part of the memory.
const small_arraybuffer = obtain_arraybuffer(small_buffer);
// Its underlying `ArrayBuffer`.
const big_arraybuffer = obtain_arraybuffer(big_buffer);

console.info(test_arraybuffer.byteLength); // 10
console.info(zero_sized_arraybuffer.byteLength); // 0
console.info(small_arraybuffer.byteLength); // 3
console.info(big_arraybuffer.byteLength); // 4096

  • Das ist alles schön und gut … aber hast du eigentlich die Frage von OP beantwortet? Wenn ja, ist es begraben…

    – Tustin2121

    14. Mai 2018 um 16:42 Uhr

  • Gute Antwort! Im obtain_arraybuffer: buf.buffer.subarray scheint nicht zu existieren. Hast du gemeint buf.buffer.slice Hier?

    – Alltagsproduktiv

    2. Juli 2018 um 17:41 Uhr


  • @alltagsproduktiv Danke. Wie Sie im Bearbeitungsverlauf sehen können, habe ich tatsächlich verwendet ArrayBuffer.prototype.slice und später modifiziert zu Uint8Array.prototype.subarray. Oh, und ich habe es falsch gemacht. Wahrscheinlich war ich damals etwas verwirrt. Dank dir ist jetzt alles gut.

    – Константин Ван

    8. Juli 2018 um 7:18 Uhr

Verwenden Sie das folgende ausgezeichnete npm-Paket: to-arraybuffer.

Oder Sie können es selbst implementieren. Wenn Ihr Puffer aufgerufen wird bufmach das:

buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength)

  • Das ist alles schön und gut … aber hast du eigentlich die Frage von OP beantwortet? Wenn ja, ist es begraben…

    – Tustin2121

    14. Mai 2018 um 16:42 Uhr

  • Gute Antwort! Im obtain_arraybuffer: buf.buffer.subarray scheint nicht zu existieren. Hast du gemeint buf.buffer.slice Hier?

    – Alltagsproduktiv

    2. Juli 2018 um 17:41 Uhr


  • @alltagsproduktiv Danke. Wie Sie im Bearbeitungsverlauf sehen können, habe ich tatsächlich verwendet ArrayBuffer.prototype.slice und später modifiziert zu Uint8Array.prototype.subarray. Oh, und ich habe es falsch gemacht. Wahrscheinlich war ich damals etwas verwirrt. Dank dir ist jetzt alles gut.

    – Константин Ван

    8. Juli 2018 um 7:18 Uhr

1645704914 13 Konvertieren Sie einen binaren NodeJS Puffer in einen JavaScript ArrayBuffer
Benny Neugebauer

Sie können an eine denken ArrayBuffer als getippt Buffer.

Ein ArrayBuffer benötigt daher immer einen Typ (den sogenannten “Array Buffer View”). Typischerweise die Array-Pufferansicht hat eine Art Uint8Array oder Uint16Array.

Dazu gibt es einen guten Artikel von Renato Mangini Konvertieren zwischen einem ArrayBuffer und einem String.

Die wesentlichen Teile habe ich in einem Codebeispiel (für Node.js) zusammengefasst. Es zeigt auch, wie man zwischen den eingegebenen konvertiert ArrayBuffer und die untypisierten Buffer.

function stringToArrayBuffer(string) {
  const arrayBuffer = new ArrayBuffer(string.length);
  const arrayBufferView = new Uint8Array(arrayBuffer);
  for (let i = 0; i < string.length; i++) {
    arrayBufferView[i] = string.charCodeAt(i);
  }
  return arrayBuffer;
}

function arrayBufferToString(buffer) {
  return String.fromCharCode.apply(null, new Uint8Array(buffer));
}

const helloWorld = stringToArrayBuffer('Hello, World!'); // "ArrayBuffer" (Uint8Array)
const encodedString = new Buffer(helloWorld).toString('base64'); // "string"
const decodedBuffer = Buffer.from(encodedString, 'base64'); // "Buffer"
const decodedArrayBuffer = new Uint8Array(decodedBuffer).buffer; // "ArrayBuffer" (Uint8Array)

console.log(arrayBufferToString(decodedArrayBuffer)); // prints "Hello, World!"

843010cookie-checkKonvertieren Sie einen binären NodeJS-Puffer in einen JavaScript-ArrayBuffer

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy