サーチ…
備考
型付き配列は、最初はKhronosエディタの草案で指定され、後でECMAScript 6§24と§22.2で標準化されました 。
ブロブは、W3C File API作業草案で指定されます 。
BlobとArrayBuffersの間の変換
JavaScriptには、ブラウザでバイナリデータを表現する2つの主な方法があります。 ArrayBuffers / TypedArraysには、直接操作できる可変長のバイナリデータが含まれています。ブロブには不変のバイナリデータが含まれています。このバイナリデータは、非同期のFileインターフェイスを介してのみアクセスできます。
Blob
をArrayBuffer
変換する(非同期)
var blob = new Blob(["\x01\x02\x03\x04"]),
fileReader = new FileReader(),
array;
fileReader.onload = function() {
array = this.result;
console.log("Array contains", array.byteLength, "bytes.");
};
fileReader.readAsArrayBuffer(blob);
Promise
(非同期)を使用してBlob
をArrayBuffer
変換する
var blob = new Blob(["\x01\x02\x03\x04"]);
var arrayPromise = new Promise(function(resolve) {
var reader = new FileReader();
reader.onloadend = function() {
resolve(reader.result);
};
reader.readAsArrayBuffer(blob);
});
arrayPromise.then(function(array) {
console.log("Array contains", array.byteLength, "bytes.");
});
ArrayBuffer
または型付き配列をBlob
変換する
var array = new Uint8Array([0x04, 0x06, 0x07, 0x08]);
var blob = new Blob([array]);
DataViewsでArrayBuffersを操作する
DataViewsは、オブジェクト全体を単一の型の配列として表示するのではなく、ArrayBufferから個々の値を読み書きするメソッドを提供します。ここでは2バイトを個別に設定し、それらを16ビットの符号なし整数、つまりビッグエンディアンからリトルエンディアンの順に解釈します。
var buffer = new ArrayBuffer(2);
var view = new DataView(buffer);
view.setUint8(0, 0xFF);
view.setUint8(1, 0x01);
console.log(view.getUint16(0, false)); // 65281
console.log(view.getUint16(0, true)); // 511
Base64文字列からTypedArrayを作成する
var data =
'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACN' +
'byblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHx' +
'gljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
var characters = atob(data);
var array = new Uint8Array(characters.length);
for (var i = 0; i < characters.length; i++) {
array[i] = characters.charCodeAt(i);
}
型付き配列の使用
TypedArraysは、固定長可変バイナリArrayBufferに異なるビューを提供する型のセットです。ほとんどの場合、割り当てられたすべての値を特定の数値型に強制する配列のように動作します。 ArrayBufferインスタンスをTypedArrayコンストラクタに渡して、そのデータの新しいビューを作成することができます。
var buffer = new ArrayBuffer(8);
var byteView = new Uint8Array(buffer);
var floatView = new Float64Array(buffer);
console.log(byteView); // [0, 0, 0, 0, 0, 0, 0, 0]
console.log(floatView); // [0]
byteView[0] = 0x01;
byteView[1] = 0x02;
byteView[2] = 0x04;
byteView[3] = 0x08;
console.log(floatView); // [6.64421383e-316]
ArrayBuffersは、 .slice(...)
メソッドを使用して直接またはTypedArrayビューを使用してコピーできます。
var byteView2 = byteView.slice();
var floatView2 = new Float64Array(byteView2.buffer);
byteView2[6] = 0xFF;
console.log(floatView); // [6.64421383e-316]
console.log(floatView2); // [7.06327456e-304]
イメージファイルのバイナリ表現の取得
File APIを使用してファイルをロードする方法を理解していることが前提です。
// preliminary code to handle getting local file and finally printing to console
// the results of our function ArrayBufferToBinary().
var file = // get handle to local file.
var reader = new FileReader();
reader.onload = function(event) {
var data = event.target.result;
console.log(ArrayBufferToBinary(data));
};
reader.readAsArrayBuffer(file); //gets an ArrayBuffer of the file
今度は、 DataView
を使用してファイルデータを1と0に実際に変換しDataView
。
function ArrayBufferToBinary(buffer) {
// Convert an array buffer to a string bit-representation: 0 1 1 0 0 0...
var dataView = new DataView(buffer);
var response = "", offset = (8/8);
for(var i = 0; i < dataView.byteLength; i += offset) {
response += dataView.getInt8(i).toString(2);
}
return response;
}
DataView
すると、数値データを読み書きできます。 getInt8
は、データをバイト位置(ここでは0
)からArrayBuffer
で渡された値を符号付き8ビット整数表現に変換し、 toString(2)
は8ビット整数をバイナリ表現形式(つまり1と0の)。
ファイルはバイトとして保存されます。 'マジック'オフセット値は、ファイルをバイト単位で格納すること、すなわち8ビット整数として8ビット整数表現で読み込むことによって得られることによって得られます。バイト保存された(つまり8ビットの)ファイルを32ビット整数に読み込もうとすると、32/8 = 4がバイトスペースの数になります。これはバイトオフセット値です。
このタスクでは、 DataView
は過剰です。データのエンディアンまたは異質性が発生した場合(たとえば、異なるベースでエンコードされたヘッダーを持つPDFファイルを読み込み、その値を意味のあるものに抽出したい場合など)、これらは一般的に使用されます。テキスト表現をしたいだけなので、異質性は気にしません。
はるかに優れた、より短期的な解決策は、 ArrayBuffer
全体を符号なし8ビット整数で構成されたUInt8Array
型付き配列を使用してUInt8Array
ことができます。
function ArrayBufferToBinary(buffer) {
var uint8 = new Uint8Array(buffer);
return uint8.reduce((binary, uint8) => binary + uint8.toString(2), "");
}
arrayBufferを反復する
arrayBufferを反復処理する便利な方法として、フードの下にDataView
メソッドを実装する単純なイテレータを作成できます。
var ArrayBufferCursor = function() {
var ArrayBufferCursor = function(arrayBuffer) {
this.dataview = new DataView(arrayBuffer, 0);
this.size = arrayBuffer.byteLength;
this.index = 0;
}
ArrayBufferCursor.prototype.next = function(type) {
switch(type) {
case 'Uint8':
var result = this.dataview.getUint8(this.index);
this.index += 1;
return result;
case 'Int16':
var result = this.dataview.getInt16(this.index, true);
this.index += 2;
return result;
case 'Uint16':
var result = this.dataview.getUint16(this.index, true);
this.index += 2;
return result;
case 'Int32':
var result = this.dataview.getInt32(this.index, true);
this.index += 4;
return result;
case 'Uint32':
var result = this.dataview.getUint32(this.index, true);
this.index += 4;
return result;
case 'Float':
case 'Float32':
var result = this.dataview.getFloat32(this.index, true);
this.index += 4;
return result;
case 'Double':
case 'Float64':
var result = this.dataview.getFloat64(this.index, true);
this.index += 8;
return result;
default:
throw new Error("Unknown datatype");
}
};
ArrayBufferCursor.prototype.hasNext = function() {
return this.index < this.size;
}
return ArrayBufferCursor;
});
次のようにイテレータを作成できます:
var cursor = new ArrayBufferCursor(arrayBuffer);
hasNext
を使ってアイテムがまだ存在するかどうかを調べることができます
for(;cursor.hasNext();) {
// There's still items to process
}
next
方法を使って次の値を取ることができます:
var nextValue = cursor.next('Float');
このようなイテレータを使用すると、バイナリデータを処理する独自のパーサーを作成するのが簡単になります。