Buscar..


Observaciones

Las matrices mecanografiadas fueron especificadas originalmente por un borrador del editor de Khronos , y luego estandarizadas en ECMAScript 6 §24 y §22.2 .

Las manchas son especificadas por el borrador de trabajo de la API del archivo W3C .

Conversión entre Blobs y ArrayBuffers

JavaScript tiene dos formas principales de representar datos binarios en el navegador. ArrayBuffers / TypedArrays contienen datos binarios mutables (aunque aún de longitud fija) que puede manipular directamente. Los blobs contienen datos binarios inmutables a los que solo se puede acceder a través de la interfaz asíncrona de archivos.

Convertir un Blob en un ArrayBuffer (asíncrono)

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

Convertir un Blob en un ArrayBuffer usando una Promise (asíncrono)

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

Convertir un ArrayBuffer o una matriz escrita en un Blob

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

var blob = new Blob([array]);

Manipular ArrayBuffers con DataViews

Las vistas de datos proporcionan métodos para leer y escribir valores individuales desde un ArrayBuffer, en lugar de ver todo como una matriz de un solo tipo. Aquí establecemos dos bytes individualmente y luego los interpretamos juntos como un entero sin signo de 16 bits, primero big-endian y luego 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

Creando un TypedArray desde una cadena 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);
}

Usando TypedArrays

TypedArrays es un conjunto de tipos que proporcionan diferentes vistas en ArrayBuffers binarios modulables de longitud fija. En su mayor parte, actúan como matrices que obligan a todos los valores asignados a un tipo numérico dado. Puede pasar una instancia de ArrayBuffer a un constructor de TypedArray para crear una nueva vista de sus datos.

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 puede copiarse usando el .slice(...) , ya sea directamente oa través de 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]

Obtención de representación binaria de un archivo de imagen.

Este ejemplo está inspirado en esta pregunta .

Asumiremos que sabe cómo cargar un archivo utilizando la API de archivos .

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

Ahora realizamos la conversión real de los datos del archivo en 1 y 0 usando 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 s le permite leer / escribir datos numéricos; getInt8 convierte los datos de la posición de byte, aquí 0 , el valor pasado en ArrayBuffer a la representación de enteros de 8 bits con signo, y toString(2) convierte el entero de 8 bits en formato de representación binario (es decir, una cadena de 1 y 0's).

Los archivos se guardan como bytes. El valor de compensación 'mágico' se obtiene al observar que estamos tomando archivos almacenados como bytes, es decir, como enteros de 8 bits y leiéndolos en una representación de enteros de 8 bits. Si estuviéramos tratando de leer nuestros archivos de bytes guardados (es decir, 8 bits) en enteros de 32 bits, notamos que 32/8 = 4 es el número de espacios de bytes, que es nuestro valor de compensación de bytes.


Para esta tarea, los DataView s son excesivos. Por lo general, se utilizan en casos en los que se encuentran datos endianes o heterogéneos (por ejemplo, al leer archivos PDF, que tienen encabezados codificados en diferentes bases y nos gustaría extraer ese valor de manera significativa). Debido a que solo queremos una representación textual, no nos importa la heterogeneidad, ya que nunca es necesario

Se puede encontrar una solución mucho mejor, y más corta, utilizando una UInt8Array tipo UInt8Array , que trata a ArrayBuffer completo como compuesto de enteros de 8 bits sin signo:

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

Iterando a través de un arrayBuffer

Para una manera conveniente de iterar a través de un arrayBuffer, puede crear un iterador simple que implemente los métodos DataView bajo el capó:

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

A continuación, puede crear un iterador como este:

var cursor = new ArrayBufferCursor(arrayBuffer);

Puedes usar el hasNext para verificar si todavía hay elementos

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

Puedes usar el next método para tomar el siguiente valor:

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

Con tal iterador, escribir su propio analizador para procesar datos binarios se vuelve bastante fácil.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow