Suche…
Bemerkungen
Typisierte Arrays wurden ursprünglich durch den Entwurf eines Khronos-Editors festgelegt und später in ECMAScript 6 §24 und §22.2 standardisiert .
Blobs werden im W3C File API-Arbeitsentwurf angegeben .
Konvertierung zwischen Blobs und ArrayBuffers
JavaScript bietet zwei Hauptmethoden, um binäre Daten im Browser darzustellen. ArrayBuffers / TypedArrays enthalten veränderliche (aber immer noch feste Längen) Binärdaten, die Sie direkt bearbeiten können. Blobs enthalten unveränderliche Binärdaten, auf die nur über die asynchrone Dateischnittstelle zugegriffen werden kann.
Konvertieren eines Blob
in einen ArrayBuffer
(asynchron)
var blob = new Blob(["\x01\x02\x03\x04"]),
fileReader = new FileReader(),
array;
fileReader.onload = function() {
array = this.result;
console.log("Array contains", array.byteLength, "bytes.");
};
fileReader.readAsArrayBuffer(blob);
Konvertieren eines Blob
in einen ArrayBuffer
mit einem Promise
(asynchron)
var blob = new Blob(["\x01\x02\x03\x04"]);
var arrayPromise = new Promise(function(resolve) {
var reader = new FileReader();
reader.onloadend = function() {
resolve(reader.result);
};
reader.readAsArrayBuffer(blob);
});
arrayPromise.then(function(array) {
console.log("Array contains", array.byteLength, "bytes.");
});
Konvertieren Sie ein ArrayBuffer
oder ein typisiertes Array in einen Blob
var array = new Uint8Array([0x04, 0x06, 0x07, 0x08]);
var blob = new Blob([array]);
ArrayBuffers mit DataViews bearbeiten
DataViews bieten Methoden zum Lesen und Schreiben einzelner Werte aus einem ArrayBuffer, anstatt das gesamte Objekt als Array eines einzelnen Typs anzuzeigen. Hier setzen wir zwei Bytes einzeln und interpretieren sie dann gemeinsam als vorzeichenlose 16-Bit-Ganzzahl, zuerst Big-Endian, dann Little-Endian.
var buffer = new ArrayBuffer(2);
var view = new DataView(buffer);
view.setUint8(0, 0xFF);
view.setUint8(1, 0x01);
console.log(view.getUint16(0, false)); // 65281
console.log(view.getUint16(0, true)); // 511
Erstellen eines TypedArray aus einer Base64-Zeichenfolge
var data =
'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACN' +
'byblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHx' +
'gljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
var characters = atob(data);
var array = new Uint8Array(characters.length);
for (var i = 0; i < characters.length; i++) {
array[i] = characters.charCodeAt(i);
}
Verwendung von TypedArrays
TypedArrays sind eine Reihe von Typen, die unterschiedliche Ansichten von veränderbaren binären ArrayBuffers mit fester Länge bieten. Meist handelt es sich dabei um Arrays , die alle einem gegebenen numerischen Typ zugewiesenen Werte erzwingen. Sie können eine ArrayBuffer-Instanz an einen TypedArray-Konstruktor übergeben, um eine neue Ansicht der Daten zu erstellen.
var buffer = new ArrayBuffer(8);
var byteView = new Uint8Array(buffer);
var floatView = new Float64Array(buffer);
console.log(byteView); // [0, 0, 0, 0, 0, 0, 0, 0]
console.log(floatView); // [0]
byteView[0] = 0x01;
byteView[1] = 0x02;
byteView[2] = 0x04;
byteView[3] = 0x08;
console.log(floatView); // [6.64421383e-316]
ArrayBuffers können mit der .slice(...)
-Methode entweder direkt oder über eine TypedArray-Ansicht kopiert werden.
var byteView2 = byteView.slice();
var floatView2 = new Float64Array(byteView2.buffer);
byteView2[6] = 0xFF;
console.log(floatView); // [6.64421383e-316]
console.log(floatView2); // [7.06327456e-304]
Binäre Darstellung einer Bilddatei abrufen
Dieses Beispiel ist von dieser Frage inspiriert.
Wir gehen davon aus, dass Sie wissen, wie Sie eine Datei mithilfe der Datei-API laden .
// preliminary code to handle getting local file and finally printing to console
// the results of our function ArrayBufferToBinary().
var file = // get handle to local file.
var reader = new FileReader();
reader.onload = function(event) {
var data = event.target.result;
console.log(ArrayBufferToBinary(data));
};
reader.readAsArrayBuffer(file); //gets an ArrayBuffer of the file
Jetzt führen wir die eigentliche Konvertierung der DataView
und DataView
mithilfe einer DataView
:
function ArrayBufferToBinary(buffer) {
// Convert an array buffer to a string bit-representation: 0 1 1 0 0 0...
var dataView = new DataView(buffer);
var response = "", offset = (8/8);
for(var i = 0; i < dataView.byteLength; i += offset) {
response += dataView.getInt8(i).toString(2);
}
return response;
}
DataView
Sie numerische Daten lesen / schreiben. getInt8
konvertiert die Daten von der Byte-Position - hier 0
, der übergebene Wert - im ArrayBuffer
in eine vorzeichenbehaftete 8-Bit-Ganzzahlendarstellung, und toString(2)
konvertiert die 8-Bit-Ganzzahl in ein binäres Darstellungsformat (dh eine Zeichenfolge von 1 und 0).
Dateien werden als Bytes gespeichert. Der "magische" Versatzwert wird erhalten, indem wir feststellen, dass Dateien, die als Bytes gespeichert sind, dh als 8-Bit-Ganzzahlen, in 8-Bit-Integer-Darstellung gelesen werden. Wenn wir versuchen würden, unsere byte-gespeicherten Dateien (dh 8 Bits) in 32-Bit-Ganzzahlen zu lesen, würden wir feststellen, dass 32/8 = 4 die Anzahl der Byte-Leerzeichen ist, was unser Byte-Offset-Wert ist.
Für diese Aufgabe sind DataView
s übertrieben. Sie werden in der Regel in Fällen verwendet, in denen Endianness oder Heterogenität von Daten auftreten (z. B. beim Lesen von PDF-Dateien, deren Header in verschiedenen Basen codiert sind und wir diesen Wert sinnvoll extrahieren möchten). Da wir nur eine Textdarstellung wünschen, ist uns die Heterogenität nicht wichtig, da dies niemals erforderlich ist
Eine viel bessere und kürzere Lösung kann mit einem Array vom Typ UInt8Array
gefunden werden, das den gesamten ArrayBuffer
als aus vorzeichenlosen 8-Bit-Ganzzahlen behandelt:
function ArrayBufferToBinary(buffer) {
var uint8 = new Uint8Array(buffer);
return uint8.reduce((binary, uint8) => binary + uint8.toString(2), "");
}
Iteration durch einen arrayBuffer
Um einen ArrayBuffer bequem durchlaufen zu können, können Sie einen einfachen Iterator erstellen, der die DataView
Methoden unter der Haube implementiert:
var ArrayBufferCursor = function() {
var ArrayBufferCursor = function(arrayBuffer) {
this.dataview = new DataView(arrayBuffer, 0);
this.size = arrayBuffer.byteLength;
this.index = 0;
}
ArrayBufferCursor.prototype.next = function(type) {
switch(type) {
case 'Uint8':
var result = this.dataview.getUint8(this.index);
this.index += 1;
return result;
case 'Int16':
var result = this.dataview.getInt16(this.index, true);
this.index += 2;
return result;
case 'Uint16':
var result = this.dataview.getUint16(this.index, true);
this.index += 2;
return result;
case 'Int32':
var result = this.dataview.getInt32(this.index, true);
this.index += 4;
return result;
case 'Uint32':
var result = this.dataview.getUint32(this.index, true);
this.index += 4;
return result;
case 'Float':
case 'Float32':
var result = this.dataview.getFloat32(this.index, true);
this.index += 4;
return result;
case 'Double':
case 'Float64':
var result = this.dataview.getFloat64(this.index, true);
this.index += 8;
return result;
default:
throw new Error("Unknown datatype");
}
};
ArrayBufferCursor.prototype.hasNext = function() {
return this.index < this.size;
}
return ArrayBufferCursor;
});
Sie können dann einen Iterator wie folgt erstellen:
var cursor = new ArrayBufferCursor(arrayBuffer);
Mit hasNext
können hasNext
prüfen, ob noch Elemente vorhanden sind
for(;cursor.hasNext();) {
// There's still items to process
}
Sie können die next
Methode verwenden, um den nächsten Wert zu übernehmen:
var nextValue = cursor.next('Float');
Mit einem solchen Iterator wird das Schreiben eines eigenen Parsers zur Verarbeitung binärer Daten ziemlich einfach.