ArrayBuffers werden zum Transport von Rohdaten verwendet und mehrere neue APIs basieren darauf, darunter WebSockets, Web Intents 2](https://www.html5rocks.com/en/tutorials/file/xhr2/) und WebWorkers. Da sie jedoch erst vor Kurzem in der JavaScript-Welt angekommen sind, werden sie manchmal falsch interpretiert oder missbraucht.
Semantisch ist ein ArrayBuffer einfach ein Array von Bytes, das durch eine bestimmte Maske betrachtet wird.
Diese Maske, eine Instanz von ArrayBufferView, definiert, wie Bytes an die erwartete Struktur des Inhalts ausgerichtet werden. Wenn Sie beispielsweise wissen, dass die Bytes in einem ArrayBuffer ein Array von 16-Bit-unsignierten Ganzzahlen darstellen, können Sie das ArrayBuffer einfach in eine Uint16Array
-Ansicht einbetten und die Elemente mithilfe der eckigen Klammern so bearbeiten, als wäre Uint16Array
ein Ganzzahlarray:
// suppose buf contains the bytes [0x02, 0x01, 0x03, 0x07]
// notice the multibyte values respect the hardware endianess, which is little-endian in x86
var bufView = new Uint16Array(buf);
if (bufView[0]===258) { // 258 === 0x0102
console.log("ok");
}
bufView[0] = 255; // buf now contains the bytes [0xFF, 0x00, 0x03, 0x07]
bufView[0] = 0xff05; // buf now contains the bytes [0x05, 0xFF, 0x03, 0x07]
bufView[1] = 0x0210; // buf now contains the bytes [0x05, 0xFF, 0x10, 0x02]
Eine häufig gestellte praktische Frage zu ArrayBuffers ist, wie eine String
in eine ArrayBuffer
und umgekehrt umgewandelt wird. Da ein ArrayBuffer in Wirklichkeit ein Byte-Array ist, erfordert diese Konvertierung, dass sich beide Enden darauf einigen, wie die Zeichen im String als Bytes dargestellt werden. Diese „Vereinbarung“ haben Sie wahrscheinlich schon einmal gesehen: Es ist die Zeichencodierung des Strings. Die üblichen „Vereinbarungsbedingungen“ sind beispielsweise Unicode UTF-16 und iso8859-1. Angenommen, Sie und die andere Partei haben sich auf die UTF-16-Codierung geeinigt, könnte der Conversion-Code so aussehen:
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint16Array(buf));
}
function str2ab(str) {
var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
Beachten Sie die Verwendung von Uint16Array
. Dies ist eine ArrayBuffer-Ansicht, bei der die Bytes der ArrayBuffers als 16‑Bit-Elemente ausgerichtet werden. Die Zeichencodierung wird nicht selbst verarbeitet, sondern von String.fromCharCode
und str.charCodeAt
als Unicode.
Eine beliebte StackOverflow-Frage zu diesem Thema enthält eine stark bewertete Antwort mit einer etwas komplizierten Lösung für die Umwandlung: Erstellen Sie eine FileReader
als Konverter und geben Sie eine Blob
mit dem String ein. Diese Methode funktioniert zwar, ist aber schwer lesbar und ich vermute, dass sie langsam ist. Da unbegründete Verdächtigungen in der Geschichte der Menschheit zu vielen Fehlern geführt haben, sollten wir hier einen wissenschaftlicheren Ansatz verfolgen. Ich habe die beiden Methoden mit jsperf verglichen und das Ergebnis bestätigt meinen Verdacht. Sehen Sie sich die Demo hier an.
In Chrome 20 ist es fast 27-mal schneller, den direkten ArrayBuffer
-Manipulationscode in diesem Artikel zu verwenden, als die FileReader
/Blob
-Methode.