Ricerca…


Osservazioni

Gli array tipizzati sono stati originariamente specificati da un progetto editor di Khronos e successivamente standardizzati in ECMAScript 6 §24 e §22.2 .

I Blob sono specificati dal draft di lavoro dell'API File W3C .

Conversione tra Blob e ArrayBuffers

JavaScript ha due metodi principali per rappresentare i dati binari nel browser. ArrayBuffers / TypedArrays contengono dati binari mutabili (sebbene ancora fissi) che possono essere manipolati direttamente. I BLOB contengono dati binari immutabili a cui è possibile accedere solo tramite l'interfaccia File asincrona.

Convertire un Blob in un ArrayBuffer (asincrono)

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

Convertire un Blob in un ArrayBuffer usando una Promise (asincrona)

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.");
});

Converti un ArrayBuffer o un array digitato in un Blob

var array = new Uint8Array([0x04, 0x06, 0x07, 0x08]);

var blob = new Blob([array]);

Manipolazione di ArrayBuffers con DataView

DataViews fornisce metodi per leggere e scrivere valori individuali da un ArrayBuffer, invece di visualizzare l'intera cosa come una matrice di un singolo tipo. Qui impostiamo due byte singolarmente, quindi li interpretiamo insieme come un numero intero senza segno a 16 bit, prima big-endian poi 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

Creazione di un oggetto TypedArray da una stringa Base64

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

Utilizzando TypedArrays

TypedArrays sono un insieme di tipi che forniscono viste differenti in ArrayBuffer binari mutabili a lunghezza fissa. Per la maggior parte, si comportano come matrici che costringono tutti i valori assegnati a un determinato tipo numerico. È possibile passare un'istanza ArrayBuffer a un costruttore TypedArray per creare una nuova vista dei propri dati.

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 può essere copiato utilizzando il .slice(...) , direttamente o tramite una vista TypedArray.

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]

Ottenere la rappresentazione binaria di un file immagine

Questo esempio è ispirato da questa domanda .

Supponiamo che tu sappia come caricare un file utilizzando l'API File .

// 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

Ora eseguiamo la conversione effettiva dei dati del file in 1 e 0 utilizzando un 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 consente di leggere / scrivere dati numerici; getInt8 converte i dati dalla posizione di byte - qui 0 , il valore passato - ArrayBuffer alla rappresentazione di interi a 8 bit con ArrayBuffer e toString(2) converte il numero intero di 8 bit in formato di rappresentazione binario (cioè una stringa di 1 e 0 di).

I file vengono salvati come byte. Il valore di offset "magico" si ottiene notando che stiamo caricando i file come byte, ad esempio come interi a 8 bit e leggendoli nella rappresentazione di numeri interi a 8 bit. Se stessimo cercando di leggere i nostri file salvati in byte (cioè 8 bit) in numeri interi a 32 bit, noteremmo che 32/8 = 4 è il numero di spazi di byte, che è il nostro valore di offset di byte.


Per questa attività, i DataView sono eccessivi. Solitamente vengono utilizzati nei casi in cui si riscontrano endianness o eterogeneità dei dati (ad esempio nella lettura di file PDF, che hanno intestazioni codificate in basi diverse e vorremmo estrarre significativamente quel valore). Perché vogliamo solo una rappresentazione testuale, non ci interessa l'eterogeneità come non c'è mai bisogno

Una soluzione molto migliore - e più breve - può essere trovata usando un array tipizzato UInt8Array , che tratta l'intero ArrayBuffer come composto da interi a 8 bit senza segno:

function ArrayBufferToBinary(buffer) {
    var uint8 = new Uint8Array(buffer);
    return uint8.reduce((binary, uint8) => binary + uint8.toString(2), "");
}

Iterazione attraverso un arraybuffer

Per un modo conveniente di scorrere un arrayBuffer, è possibile creare un semplice iteratore che implementa i metodi DataView sotto il cofano:

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

È quindi possibile creare un iteratore come questo:

var cursor = new ArrayBufferCursor(arrayBuffer);

È possibile utilizzare hasNext per verificare se ci sono ancora elementi

for(;cursor.hasNext();) {
    // There's still items to process
}

Puoi usare il next metodo per prendere il prossimo valore:

var nextValue = cursor.next('Float');

Con un tale iteratore, scrivere il proprio parser per elaborare i dati binari diventa piuttosto facile.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow