Sök…
Anmärkningar
Typade Arrays specificerades ursprungligen av en Khronos-redaktörsutkast och standardiserades senare i ECMAScript 6 §24 och §22.2 .
Blobs specificeras av W3C File API: s arbetsutkast .
Konvertering mellan Blobs och ArrayBuffers
JavaScript har två huvudsakliga sätt att representera binär data i webbläsaren. ArrayBuffers / TypedArrays innehåller muterbara (men fortfarande med fast längd) binär data som du kan direkt manipulera. Klöver innehåller immutable binära data som bara kan nås via det asynkrona filgränssnittet.
Konvertera en Blob
till en ArrayBuffer
(asynkron)
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);
Konvertera en Blob
till en ArrayBuffer
med ett Promise
(asynkront)
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.");
});
Konvertera en ArrayBuffer
eller en ArrayBuffer
till en Blob
var array = new Uint8Array([0x04, 0x06, 0x07, 0x08]);
var blob = new Blob([array]);
Hantera ArrayBuffers med DataViews
DataViews tillhandahåller metoder för att läsa och skriva enskilda värden från en ArrayBuffer, istället för att se hela saken som en matris av en enda typ. Här ställer vi in två byte individuellt och sedan tolkar dem tillsammans som ett 16-bitars osignerat heltal, först big-endian och 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
Skapa en TypedArray från en Base64-sträng
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);
}
Använda TypedArrays
TypedArrays är en uppsättning typer som tillhandahåller olika vyer i mutanter med binär ArrayBuffers med fast längd. För det mesta fungerar de som Arrays som tvingar alla tilldelade värden till en viss numerisk typ. Du kan skicka en ArrayBuffer-instans till en TypedArray-konstruktör för att skapa en ny vy av dess data.
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 kan kopieras med .slice(...)
, antingen direkt eller genom en TypedArray-vy.
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]
Få binär representation av en bildfil
Detta exempel är inspirerat av denna fråga .
Vi antar att du vet hur du laddar en fil med 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 utför vi den faktiska konverteringen av fildata till 1 och 0 med hjälp av en 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
låter dig läsa / skriva numeriska data; getInt8
konverterar data från byte-positionen - här 0
, värdet som skickas in - i ArrayBuffer
till signerad 8-bitars toString(2)
, och toString(2)
konverterar 8-bitars heltalet till binärt representationsformat (dvs en sträng av 1 och 0 s).
Filer sparas som byte. Det "magiska" offsetvärdet erhålls genom att notera att vi tar filer lagrade som byte, dvs som 8-bitars heltal och läser det i 8-bitars heltalrepresentation. Om vi försökte läsa våra byte-sparade (dvs 8 bitar) -filer till 32-bitars heltal, noterar vi att 32/8 = 4 är antalet byte-mellanslag, vilket är vårt byte-offsetvärde.
För den här uppgiften är DataView
överdrivna. De används vanligtvis i fall där data är slut eller heterogenitet (t.ex. vid läsning av PDF-filer, som har rubriker kodade i olika baser och vi vill betydligt extrahera det värdet). Eftersom vi bara vill ha en textrepresentation bryr vi oss inte om heterogenitet eftersom det aldrig behövs
En mycket bättre - och kortare - lösning kan hittas med hjälp av en UInt8Array
, som behandlar hela ArrayBuffer
som sammansatt av osignerade 8-bitars heltal:
function ArrayBufferToBinary(buffer) {
var uint8 = new Uint8Array(buffer);
return uint8.reduce((binary, uint8) => binary + uint8.toString(2), "");
}
Iterating genom en matrisBuffer
För ett bekvämt sätt att iterera genom en arrayBuffer kan du skapa en enkel iterator som implementerar DataView
metoderna under huven:
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;
});
Du kan sedan skapa en iterator så här:
var cursor = new ArrayBufferCursor(arrayBuffer);
Du kan använda hasNext
att kontrollera om det fortfarande finns artiklar
for(;cursor.hasNext();) {
// There's still items to process
}
Du kan använda next
metod för att ta nästa värde:
var nextValue = cursor.next('Float');
Med en sådan iterator blir det ganska enkelt att skriva din egen parser för att bearbeta binära data.