`DataView` в JavaScript
В этой статье объясняется, что такое DataView
в JavaScript.
Мы подробно объясним базовое использование DataView
и приведем конкретные примеры его применения.
YouTube Video
DataView
в JavaScript
DataView
в JavaScript представляет собой удобный 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
вы можете указывать различные размеры байтов и порядок байтов (big-endian или little-endian) при чтении или записи данных, хранящихся в буфере.
Основные методы 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-битного знакового целого числа в формате little-endian, а методgetInt16
считывает это значение в формате little-endian.
Пример 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-битного числа с плавающей запятой в формате big-endian, а это значение считывается с помощьюgetFloat64
.
О порядке байтов (Endianness)
Давайте посмотрим пример чтения и записи значений в форматах big-endian и little-endian с помощью 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
данные по умолчанию сохраняются в формате big-endian (порядок байтов от старшего к младшему), но формат little-endian может быть указан по желанию. Little-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
— это мощный API для работы с двоичными данными в JavaScript. Вы можете напрямую обращаться к ArrayBuffer
, чтобы считывать и записывать данные, учитывая целые числа, числа с плавающей запятой и различия в порядке байтов (endianness). Это полезно в ситуациях, таких как сетевые коммуникации и разбор форматов файлов, и незаменимо, когда требуется управление на уровне байтов. Используя его вместе с TypedArray
, вы можете более эффективно манипулировать бинарными данными.
Вы можете следовать этой статье, используя Visual Studio Code на нашем YouTube-канале. Пожалуйста, также посмотрите наш YouTube-канал.