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);
6

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.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow