`DataView` en JavaScript

`DataView` en JavaScript

Este artículo explica DataView en JavaScript.

Explicaremos en detalle el uso básico de DataView y ejemplos específicos de su uso.

YouTube Video

DataView en JavaScript

El DataView de JavaScript es una API práctica para manipular datos almacenados en un búfer (ArrayBuffer) en varios formatos. Esto permite una lectura y escritura flexible y eficiente de datos binarios, desempeñando un papel importante en la comunicación de redes, el procesamiento de archivos y la interacción con WebAssembly.

¿Qué es DataView?

DataView proporciona una capa de vista sobre un objeto ArrayBuffer, lo que permite leer y escribir diferentes tipos de datos (como enteros, números de punto flotante y caracteres) desde cualquier desplazamiento de byte. DataView es similar a TypedArray, pero se caracteriza por su capacidad para especificar la endianidad y realizar operaciones detalladas a nivel de byte.

Sintaxis Básica de DataView

1let buffer = new ArrayBuffer(16);  // Create a 16-byte ArrayBuffer
2let view = new DataView(buffer);    // Manipulate the buffer with a DataView

DataView tiene un constructor que toma un ArrayBuffer como argumento. En este ejemplo, se crea un búfer de 16 bytes y se utiliza DataView para acceder a ese búfer. Usando DataView, puedes especificar diferentes tamaños de byte y endianidad (big-endian o little-endian) al leer o escribir datos almacenados en un búfer.

Métodos Básicos de DataView

DataView proporciona métodos para leer y escribir valores de varios tipos de datos. Se dividen principalmente en métodos get para la lectura de datos y métodos set para la escritura.

Los métodos principales se muestran a continuación.

Métodos para Leer Valores

  • getInt8(byteOffset): Lee un entero con signo de 1 byte en el desplazamiento especificado.
  • getUint8(byteOffset): Lee un entero sin signo de 1 byte en el desplazamiento especificado.
  • getInt16(byteOffset, littleEndian): Lee un entero con signo de 2 bytes.
  • getUint16(byteOffset, littleEndian): Lee un entero sin signo de 2 bytes.
  • getInt32(byteOffset, littleEndian): Lee un entero con signo de 4 bytes.
  • getUint32(byteOffset, littleEndian): Lee un entero sin signo de 4 bytes.
  • getFloat32(byteOffset, littleEndian): Lee un número de punto flotante IEEE 754 de 4 bytes.
  • getFloat64(byteOffset, littleEndian): Lee un número de punto flotante IEEE 754 de 8 bytes.

Métodos para Escribir Valores

  • setInt8(byteOffset, value): Escribe un entero con signo de 1 byte.
  • setUint8(byteOffset, value): Escribe un entero sin signo de 1 byte.
  • setInt16(byteOffset, value, littleEndian): Escribe un entero con signo de 2 bytes.
  • setUint16(byteOffset, value, littleEndian): Escribe un entero sin signo de 2 bytes.
  • setInt32(byteOffset, value, littleEndian): Escribe un entero firmado de 4 bytes.
  • setUint32(byteOffset, value, littleEndian): Escribe un entero sin signo de 4 bytes.
  • setFloat32(byteOffset, value, littleEndian): Escribe un número de punto flotante IEEE 754 de 4 bytes.
  • setFloat64(byteOffset, value, littleEndian): Escribe un número de punto flotante IEEE 754 de 8 bytes.

Mediante el uso de estos métodos, puedes leer y escribir datos almacenados en un ArrayBuffer de manera flexible.

Ejemplo de uso de DataView

Veamos un ejemplo de cómo manipular datos binarios usando DataView.

Ejemplo 1: Escribir y leer un entero de 16 bits

1let buffer = new ArrayBuffer(4);  // Create a 4-byte buffer
2let view = new DataView(buffer);
3
4// Write a 2-byte integer value in little-endian format
5view.setInt16(0, 32767, true);  // byteOffset: 0, value: 32767, littleEndian: true
6
7// Read the data in little-endian format
8let value = view.getInt16(0, true);
9console.log(value);  // Output: 32767
  • En este ejemplo, se utiliza el método setInt16 para escribir un entero firmado de 16 bits en formato little-endian, y el método getInt16 lee ese valor en little-endian.

Ejemplo 2: Escribir y leer un número de punto flotante

1let buffer = new ArrayBuffer(8);  // Create an 8-byte buffer
2let view = new DataView(buffer);
3
4// Write an 8-byte floating-point number
5view.setFloat64(0, 3.14159, false);  // byteOffset: 0, value: 3.14159, bigEndian: false
6
7// Read the data in big-endian format
8let pi = view.getFloat64(0, false);
9console.log(pi);  // Output: 3.14159
  • En este ejemplo, se utiliza el método setFloat64 para escribir un número de punto flotante de 64 bits en formato big-endian, y ese valor se lee con getFloat64.

Sobre el orden de bytes (Endianness)

Veamos un ejemplo de cómo leer y escribir valores en formatos big-endian y little-endian usando DataView.

 1// Example: Handling Endianness with DataView in TypeScript
 2// Create an ArrayBuffer of 4 bytes
 3const buffer = new ArrayBuffer(4);
 4const view = new DataView(buffer);
 5
 6// Store the same number (0x12345678) in both endian formats
 7// By default, DataView uses big-endian
 8view.setUint32(0, 0x12345678); // Big-endian
 9console.log("Big-endian (default):");
10console.log(buffer);
11
12// Overwrite the buffer with little-endian
13view.setUint32(0, 0x12345678, true); // Little-endian
14console.log("Little-endian:");
15console.log(buffer);
16
17// Read values back in both endian modes
18const bigEndianValue = view.getUint32(0); // Big-endian read
19const littleEndianValue = view.getUint32(0, true); // Little-endian read
20
21console.log("Read as Big-endian:", bigEndianValue.toString(16));
22console.log("Read as Little-endian:", littleEndianValue.toString(16));

En los métodos de DataView, los datos se almacenan por defecto en big-endian (orden de bytes del más significativo al menos significativo), pero opcionalmente se puede especificar el formato little-endian. Little-endian invierte el orden de los bytes (del menos significativo al más significativo). Es importante manejar correctamente la endianidad de los datos porque diferentes sistemas y protocolos de red utilizan diferentes endianidades.

Diferencia con TypedArray

Veamos las diferencias entre DataView y TypedArray.

 1// Example: TypedArray vs DataView
 2
 3// Create a 8-byte buffer
 4const buffer = new ArrayBuffer(8);
 5
 6// --- Using TypedArray (Int32Array) ---
 7const int32View = new Int32Array(buffer);
 8int32View[0] = 42;
 9int32View[1] = 100;
10
11console.log("TypedArray (Int32Array):");
12console.log(int32View); // Int32Array [42, 100]
13
14// --- Using DataView ---
15const dataView = new DataView(buffer);
16
17// Write different types of data at arbitrary byte offsets
18dataView.setInt8(0, 65);         // 1 byte
19dataView.setUint16(1, 500, true); // 2 bytes, little-endian
20dataView.setFloat32(3, 3.14, true); // 4 bytes, little-endian
21
22console.log("\nDataView:");
23console.log("Int8 at 0:", dataView.getInt8(0));      // 65
24console.log("Uint16 at 1:", dataView.getUint16(1, true)); // 500
25console.log("Float32 at 3:", dataView.getFloat32(3, true)); // 3.14
26
27/*
28Output:
29TypedArray (Int32Array):
30Int32Array [42, 100]
31
32DataView:
33Int8 at 0: 65
34Uint16 at 1: 500
35Float32 at 3: 3.140000104904175
36*/

TypedArray también ofrece operaciones de buffer basadas en ArrayBuffer, pero TypedArray es adecuado para operar con datos contiguos de longitud fija y formato fijo para cada tipo de dato. Por otro lado, DataView puede operar de manera flexible con diferentes tipos de datos y también permite el control sobre la endianness. Por lo tanto, DataView es adecuado para analizar y construir datos binarios complejos.

Resumen

DataView es una API poderosa para manejar datos binarios en JavaScript. Puedes acceder directamente a ArrayBuffer para leer y escribir datos teniendo en cuenta enteros, números de punto flotante y diferencias en la endianness. Es útil en situaciones como la comunicación en red y el análisis de formatos de archivo, y es indispensable cuando se requiere control a nivel de byte. Al usarlo junto con TypedArray, puedes manipular datos binarios de manera más eficiente.

Puedes seguir el artículo anterior utilizando Visual Studio Code en nuestro canal de YouTube. Por favor, también revisa nuestro canal de YouTube.

YouTube Video