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 的區別
讓我們看看 DataView 與 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 同樣基於 ArrayBuffer 提供緩衝操作,但 TypedArray 更適合用於操作固定長度且每種數據類型具有固定格式的連續數據。另一方面,DataView 可以靈活地操作不同的數據類型,並允許控制字節序。因此,DataView 適用於解析和構建複雜的二進制數據。
總結
DataView 是用於處理 JavaScript 中二進制數據的強大 API。您可以直接訪問 ArrayBuffer 以讀取和寫入數據,同時考慮整數、浮點數以及大小端的差異。它在網絡通信和文件格式解析等場合非常有用,並且在需要字節級別控制時不可或缺。與 TypedArray 一起使用時,您可以更有效率地操作二進位資料。
您可以在我們的 YouTube 頻道上使用 Visual Studio Code 來跟隨上述文章一起學習。 請也查看我們的 YouTube 頻道。