JavaScript 的 `DataView`

JavaScript 的 `DataView`

本文將解釋 JavaScript 中的 DataView

我們將詳細解釋 DataView 的基本用法及其具體使用範例。

YouTube Video

JavaScript 的 DataView

JavaScript 的 DataView 是一種便捷的 API,用於以不同格式操作存儲於緩衝區(ArrayBuffer)中的數據。這使得二進制數據的讀寫更加靈活和高效,在網絡通信、文件處理以及與 WebAssembly 的交互中發揮了重要作用。

什麼是 DataView

DataView 提供了一個基於 ArrayBuffer 對象的視圖層,允許你從任何字節偏移位置讀取和寫入不同類型的數據(如整數、浮點數以及字符)。DataView 類似於 TypedArray,但其特點是能夠指定字節序(大小端)並進行詳細的字節級操作。

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 方法中,數據默認以大端(從最高有效位到最低有效位的字節順序)存儲,但可以選擇性地指定小端格式。小端格式反轉了字節順序(從最低有效位到最高有效位)。正確處理數據的位元組順序(Endian)非常重要,因為不同的系統和網路協議可能使用不同的位元組順序。

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