サーチ…


備考

型付き配列は、最初はKhronosエディタの草案で指定され、後でECMAScript 6§24§22.2で標準化されました

ブロブは、W3C File API作業草案で指定されます

BlobとArrayBuffersの間の変換

JavaScriptには、ブラウザでバイナリデータを表現する2つの主な方法があります。 ArrayBuffers / TypedArraysには、直接操作できる可変長のバイナリデータが含まれています。ブロブには不変のバイナリデータが含まれています。このバイナリデータは、非同期のFileインターフェイスを介してのみアクセスできます。

BlobArrayBuffer変換する(非同期)

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);
6

Promise (非同期)を使用してBlobArrayBuffer変換する

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');

このようなイテレータを使用すると、バイナリデータを処理する独自のパーサーを作成するのが簡単になります。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow