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