JavaScriptにおける`DataView`
この記事ではJavaScriptにおけるDataView
について説明します。
DataView
の基本的な使い方や、具体的な使用例について詳しく解説します。
YouTube Video
JavaScriptにおけるDataView
JavaScriptのDataView
は、バッファ(ArrayBuffer
)に格納されたデータをさまざまな形式で操作するための便利なAPIです。これにより、バイナリデータを柔軟かつ効率的に読み書きできるため、ネットワーク通信やファイル処理、WebAssemblyとのインターフェースで重要な役割を果たします。
DataView
とは?
DataView
は、ArrayBuffer
オブジェクトに対してビューレイヤーを提供し、任意のバイトオフセットから異なるデータ型(整数、浮動小数点数、文字など)で読み書きができるようにします。TypedArray
と似ていますが、DataView
はエンディアンの指定や、バイト単位での操作を細かく行えるのが特徴です。
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
との違い
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チャンネルもご覧ください。