JavaScript中的`DataView`

JavaScript中的`DataView`

本文解释了JavaScript中的DataView

我们将详细解释 DataView 的基本用法及其具体使用示例。

YouTube Video

JavaScript中的DataView

JavaScript的DataView是一个方便的API,用于以各种格式操作存储在缓冲区(ArrayBuffer)中的数据。这使得灵活高效地读写二进制数据成为可能,在网络通信、文件处理以及与WebAssembly的交互中扮演着重要角色。

DataView是什么?

DataViewArrayBuffer对象提供了一个视图层,允许您从任意字节偏移位置读取和写入不同的数据类型(如整数、浮点数和字符)。DataViewTypedArray类似,但它的特点是可以指定字节序并在字节级别执行详细操作。

DataView的基本语法

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

DataView有一个构造器,接受一个ArrayBuffer作为参数。在这个例子中,创建了一个16字节的缓冲区,并使用DataView访问该缓冲区。使用DataView,您可以在读取或写入缓冲区中存储的数据时指定不同的字节大小和字节序(大端或小端)。

DataView的基本方法

DataView提供了读取和写入各种数据类型的值的方法。它们主要分为用于读取数据的get方法和用于写入的set方法。

主要方法如下所示。

读取值的方法

  • getInt8(byteOffset):读取指定偏移处的1字节有符号整数。
  • getUint8(byteOffset):读取指定偏移处的1字节无符号整数。
  • getInt16(byteOffset, littleEndian):读取2字节有符号整数。
  • getUint16(byteOffset, littleEndian):读取2字节无符号整数。
  • getInt32(byteOffset, littleEndian):读取4字节有符号整数。
  • getUint32(byteOffset, littleEndian):读取4字节无符号整数。
  • getFloat32(byteOffset, littleEndian):读取一个4字节的IEEE 754浮点数。
  • getFloat64(byteOffset, littleEndian):读取一个8字节的IEEE 754浮点数。

用于写入值的方法

  • setInt8(byteOffset, value):写入一个1字节的有符号整数。
  • setUint8(byteOffset, value):写入一个1字节的无符号整数。
  • setInt16(byteOffset, value, littleEndian):写入一个2字节的有符号整数。
  • setUint16(byteOffset, value, littleEndian):写入一个2字节的无符号整数。
  • setInt32(byteOffset, value, littleEndian):写入一个4字节的有符号整数。
  • setUint32(byteOffset, value, littleEndian):写入一个4字节的无符号整数。
  • setFloat32(byteOffset, value, littleEndian):写入一个4字节的IEEE 754浮点数。
  • setFloat64(byteOffset, value, littleEndian):写入一个8字节的IEEE 754浮点数。

通过使用这些方法,可以灵活地读取和写入存储在ArrayBuffer中的数据。

DataView使用示例

让我们看一个使用 DataView 操作二进制数据的例子。

示例1:写入和读取一个16位整数

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
  • 在这个示例中,使用setInt16方法以小端格式写入一个16位有符号整数,并使用getInt16方法以小端格式读取该值。

示例2:写入和读取一个浮点数

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
  • 在这个示例中,使用setFloat64方法以大端格式写入一个64位浮点数,并使用getFloat64读取该值。

关于字节序

让我们看一个使用 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));

DataView的方法中,数据默认以大端形式存储(从最高有效字节到最低有效字节),但也可以选择以小端形式指定。小端形式会反转字节顺序(从最低有效字节到最高有效字节)。正确处理数据的字节序非常重要,因为不同的系统和网络协议使用不同的字节序。

TypedArray的区别

让我们看看 DataViewTypedArray 之间的区别。

 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也提供基于ArrayBuffer的缓冲区操作,但TypedArray适合用于按固定长度和数据类型格式连续操作数据。另一方面,DataView可以灵活地操作不同的数据类型,还可以控制字节序。因此,DataView 适用于解析和构建复杂的二进制数据。

总结

DataView 是一个在 JavaScript 中处理二进制数据的强大 API。您可以直接访问 ArrayBuffer 来读取和写入数据,同时考虑整数、浮点数以及字节序的差异。它在网络通信、文件格式解析等场景中非常有用,当需要字节级控制时是不可或缺的。与 TypedArray 一起使用时,可以更高效地操作二进制数据。

您可以在我们的YouTube频道上使用Visual Studio Code跟随上述文章进行学习。 请也查看我们的YouTube频道。

YouTube Video