Zoeken…
Opmerkingen
Typed Arrays werden oorspronkelijk gespecificeerd door een ontwerp van een Khronos-editor en later gestandaardiseerd in ECMAScript 6 §24 en §22.2 .
Blobs worden gespecificeerd door het werkontwerp van de W3C File API .
Converteren tussen Blobs en ArrayBuffers
JavaScript heeft twee primaire manieren om binaire gegevens in de browser weer te geven. ArrayBuffers / TypedArrays bevatten veranderlijke (hoewel nog steeds van vaste lengte) binaire gegevens die u rechtstreeks kunt manipuleren. Blobs bevatten onveranderlijke binaire gegevens die alleen toegankelijk zijn via de asynchrone bestandsinterface.
Een Blob
omzetten in een ArrayBuffer
(asynchroon)
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);
Converteer een Blob
naar een ArrayBuffer
met behulp van een Promise
(asynchroon)
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.");
});
Converteer een ArrayBuffer
of een getypte array naar een Blob
var array = new Uint8Array([0x04, 0x06, 0x07, 0x08]);
var blob = new Blob([array]);
ArrayBuffers manipuleren met DataViews
DataViews bieden methoden om individuele waarden van een ArrayBuffer te lezen en te schrijven, in plaats van het geheel als een array van één type te bekijken. Hier stellen we twee bytes afzonderlijk in en interpreteren ze vervolgens samen als een 16-bits geheel getal zonder teken, eerst big-endian dan 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
Een TypedArray maken op basis van een Base64-tekenreeks
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);
}
TypedArrays gebruiken
TypedArrays zijn een set typen die verschillende weergaven bieden in muteerbare binaire ArrayBuffers met een vaste lengte. Voor het grootste deel werken ze als arrays die alle toegewezen waarden tot een bepaald numeriek type dwingen. U kunt een ArrayBuffer-instantie doorgeven aan een TypedArray-constructor om een nieuwe weergave van de gegevens te maken.
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 kunnen worden gekopieerd met behulp van de .slice(...)
-methode, rechtstreeks of via een TypedArray-weergave.
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]
Binaire weergave van een afbeeldingsbestand verkrijgen
Dit voorbeeld is geïnspireerd op deze vraag .
We gaan ervan uit dat u weet hoe u een bestand kunt laden met de File API .
// 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
Nu voeren we de daadwerkelijke conversie van de bestandsgegevens uit in DataView
met behulp van een 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
's kunt u numerieke gegevens lezen / schrijven; getInt8
converteert de gegevens van de getInt8
- hier 0
, de doorgegeven waarde - in de ArrayBuffer
naar een ondertekende 8-bits weergave van een geheel getal, en toString(2)
converteert het 8-bits geheel getal naar een binaire weergave-indeling (dwz een reeks van ArrayBuffer
en 0's).
Bestanden worden opgeslagen als bytes. De 'magische' offsetwaarde wordt verkregen door op te merken dat we bestanden nemen die zijn opgeslagen als bytes, dwz als 8-bits gehele getallen, en deze lezen in een 8-bits geheel getal. Als we onze byte-opgeslagen bestanden (dwz 8 bits) proberen te lezen naar 32-bits gehele getallen, zouden we opmerken dat 32/8 = 4 het aantal byte-spaties is, wat onze byte-offsetwaarde is.
Voor deze taak zijn DataView
's overkill. Ze worden meestal gebruikt in gevallen waarin endianness of heterogeniteit van gegevens wordt aangetroffen (bijvoorbeeld bij het lezen van PDF-bestanden, met headers gecodeerd in verschillende bases en we willen die waarde zinvol extraheren). Omdat we alleen een tekstuele weergave willen, geven we niet om heterogeniteit, omdat dat nooit nodig is
Een veel betere - en kortere - oplossing kan worden gevonden met een UInt8Array
getypte array, die de hele ArrayBuffer
als samengesteld uit niet-ondertekende 8-bits gehele getallen:
function ArrayBufferToBinary(buffer) {
var uint8 = new Uint8Array(buffer);
return uint8.reduce((binary, uint8) => binary + uint8.toString(2), "");
}
Iteratie door een arrayBuffer
Voor een gemakkelijke manier om een arrayBuffer te doorlopen, kunt u een eenvoudige iterator maken die de DataView
methoden onder de motorkap implementeert:
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;
});
U kunt vervolgens een iterator als volgt maken:
var cursor = new ArrayBufferCursor(arrayBuffer);
Je kunt hasNext
om te controleren of er nog items zijn
for(;cursor.hasNext();) {
// There's still items to process
}
U kunt de next
methode gebruiken om de volgende waarde te nemen:
var nextValue = cursor.next('Float');
Met een dergelijke iterator wordt het schrijven van uw eigen parser om binaire gegevens te verwerken vrij eenvoudig.