`DataView` trong JavaScript
Bài viết này giải thích về DataView
trong JavaScript.
Chúng tôi sẽ giải thích chi tiết cách sử dụng cơ bản của DataView
và những ví dụ cụ thể về việc sử dụng nó.
YouTube Video
DataView
trong JavaScript
DataView
trong JavaScript là một API tiện lợi để xử lý dữ liệu được lưu trong một bộ đệm (ArrayBuffer
) theo nhiều định dạng khác nhau. Điều này cho phép đọc và ghi dữ liệu nhị phân linh hoạt và hiệu quả, đóng vai trò quan trọng trong giao tiếp mạng, xử lý tệp và tương tác với WebAssembly.
DataView
là gì?
DataView
cung cấp một lớp xem trên đối tượng ArrayBuffer
, cho phép bạn đọc và ghi các loại dữ liệu khác nhau (chẳng hạn như số nguyên, số thập phân và ký tự) từ bất kỳ vị trí byte nào. DataView
tương tự như TypedArray
, nhưng nó có đặc điểm là khả năng chỉ định cách sắp xếp byte (endianness) và thực hiện các thao tác chi tiết ở mức byte.
Cú pháp cơ bản của DataView
1let buffer = new ArrayBuffer(16); // Create a 16-byte ArrayBuffer
2let view = new DataView(buffer); // Manipulate the buffer with a DataView
DataView
có một hàm khởi tạo nhận một ArrayBuffer
làm tham số. Trong ví dụ này, một bộ đệm 16 byte được tạo và DataView
được sử dụng để truy cập bộ đệm đó. Sử dụng DataView
, bạn có thể chỉ định các kích cỡ byte khác nhau và cách sắp xếp byte (big-endian hoặc little-endian) khi đọc hoặc ghi dữ liệu được lưu trong bộ đệm.
Phương thức cơ bản của DataView
DataView
cung cấp các phương thức để đọc và ghi giá trị của nhiều loại dữ liệu khác nhau. Chúng chủ yếu được chia thành các phương thức get
để đọc dữ liệu và các phương thức set
để ghi.
Các phương thức chính được liệt kê dưới đây.
Phương thức để đọc giá trị
getInt8(byteOffset)
: Đọc một số nguyên có dấu 1 byte tại byte offset được chỉ định.getUint8(byteOffset)
: Đọc một số nguyên không dấu 1 byte tại byte offset được chỉ định.getInt16(byteOffset, littleEndian)
: Đọc một số nguyên có dấu 2 byte.getUint16(byteOffset, littleEndian)
: Đọc một số nguyên không dấu 2 byte.getInt32(byteOffset, littleEndian)
: Đọc một số nguyên có dấu 4 byte.getUint32(byteOffset, littleEndian)
: Đọc một số nguyên không dấu 4 byte.getFloat32(byteOffset, littleEndian)
: Đọc một số dấu phẩy động 4 byte IEEE 754.getFloat64(byteOffset, littleEndian)
: Đọc một số dấu phẩy động 8 byte IEEE 754.
Các phương thức ghi giá trị
setInt8(byteOffset, value)
: Ghi một số nguyên có dấu 1 byte.setUint8(byteOffset, value)
: Ghi một số nguyên không dấu 1 byte.setInt16(byteOffset, value, littleEndian)
: Ghi một số nguyên có dấu 2 byte.setUint16(byteOffset, value, littleEndian)
: Ghi một số nguyên không dấu 2 byte.setInt32(byteOffset, value, littleEndian)
: Ghi một số nguyên có dấu 4 byte.setUint32(byteOffset, value, littleEndian)
: Ghi một số nguyên không dấu 4 byte.setFloat32(byteOffset, value, littleEndian)
: Ghi một số dấu phẩy động 4 byte IEEE 754.setFloat64(byteOffset, value, littleEndian)
: Ghi một số dấu phẩy động 8 byte IEEE 754.
Bằng cách sử dụng các phương thức này, bạn có thể linh hoạt đọc và ghi dữ liệu được lưu trữ trong ArrayBuffer
.
Ví dụ về việc sử dụng DataView
Hãy xem một ví dụ về thao tác dữ liệu nhị phân bằng cách sử dụng DataView
.
Ví dụ 1: Ghi và đọc một số nguyên 16 bit
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
- Trong ví dụ này, phương thức
setInt16
được sử dụng để ghi một số nguyên có dấu 16 bit theo định dạng little-endian, và phương thứcgetInt16
đọc giá trị đó cũng bằng định dạng little-endian.
Ví dụ 2: Ghi và đọc một số dấu phẩy động
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
- Trong ví dụ này, phương thức
setFloat64
được sử dụng để ghi một số dấu phẩy động 64 bit theo định dạng big-endian, và giá trị đó được đọc bằnggetFloat64
.
Về thứ tự byte (Endianness)
Hãy xem một ví dụ về cách đọc và ghi giá trị với cả hai định dạng big-endian và little-endian bằng cách sử dụng 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));
Trong các phương thức của DataView
, dữ liệu được lưu trữ mặc định theo thứ tự big-endian (thứ tự byte từ byte quan trọng nhất đến byte ít quan trọng nhất), nhưng cũng có thể chỉ định thứ tự little-endian khi cần. Thứ tự little-endian đảo ngược thứ tự byte (từ byte ít quan trọng nhất đến byte quan trọng nhất). Việc xử lý đúng định dạng endian của dữ liệu là rất quan trọng vì các hệ thống và giao thức mạng khác nhau sử dụng các định dạng endian khác nhau.
Sự khác biệt so với TypedArray
Hãy xem sự khác biệt giữa DataView
và 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
cũng cung cấp các thao tác bộ đệm dựa trên ArrayBuffer
, nhưng TypedArray
phù hợp với việc thao tác dữ liệu liên tục có chiều dài cố định và định dạng cho mỗi loại dữ liệu. Mặt khác, DataView
có thể linh hoạt thao tác trên các loại dữ liệu khác nhau và cũng cho phép kiểm soát thứ tự byte (endianness). Vì vậy, DataView
phù hợp để phân tích cú pháp và xây dựng dữ liệu nhị phân phức tạp.
Tóm tắt
DataView
là một API mạnh mẽ để xử lý dữ liệu nhị phân trong JavaScript. Bạn có thể trực tiếp truy cập ArrayBuffer
để đọc và ghi dữ liệu trong khi xem xét số nguyên, số dấu phẩy động và sự khác biệt trong thứ tự byte (endianness). Nó hữu ích trong các tình huống như truyền thông mạng và phân tích định dạng tệp, và không thể thiếu khi cần kiểm soát ở cấp độ byte. Bằng cách sử dụng cùng với TypedArray
, bạn có thể thao tác dữ liệu nhị phân hiệu quả hơn.
Bạn có thể làm theo bài viết trên bằng cách sử dụng Visual Studio Code trên kênh YouTube của chúng tôi. Vui lòng ghé thăm kênh YouTube.