JavaScriptにおける`DataView`

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との違い

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*/

TypedArrayArrayBufferを基盤としたバッファ操作を提供しますが、TypedArrayはデータ型ごとに固定された長さとフォーマットで連続したデータの操作に適しています。一方、DataViewは、異なるデータ型を柔軟に操作でき、エンディアンの制御も可能です。そのため、複雑なバイナリデータの解析や構築にはDataViewが適しています。

まとめ

DataViewは、JavaScriptでバイナリデータを操作するための強力なAPIです。ArrayBuffer上に直接アクセスして、整数、浮動小数点数、エンディアンの違いを考慮しながらデータの読み書きを行うことができます。ネットワーク通信やファイルフォーマット解析などの場面で活躍し、特にバイト単位の制御が必要な場面では不可欠です。TypedArrayと併せて活用することで、より効率的なバイナリデータ操作を実現できます。

YouTubeチャンネルでは、Visual Studio Codeを用いて上記の記事を見ながら確認できます。 ぜひYouTubeチャンネルもご覧ください。

YouTube Video