ArrayBuffer は未加工データを転送するために使用され、WebSockets、Web Intents 2](https://www.html5rocks.com/en/tutorials/file/xhr2/)、WebWorkers など、いくつかの新しい API が ArrayBuffer に依存しています。ただし、JavaScript の世界に登場したばかりであるため、誤解や誤用されることがあります。
意味的には、ArrayBuffer は、特定のマスクで表示されるバイトの配列にすぎません。このマスク(ArrayBufferView のインスタンス)は、コンテンツの想定される構造に合わせてバイトがどのように配置されるかを定義します。たとえば、ArrayBuffer 内のバイトが 16 ビットの符号なし整数の配列を表していることがわかっている場合は、ArrayBuffer を Uint16Array
ビューでラップするだけで、Uint16Array
が整数配列であるかのようにかっこ構文を使用して要素を操作できます。
// suppose buf contains the bytes [0x02, 0x01, 0x03, 0x07]
// notice the multibyte values respect the hardware endianess, which is little-endian in x86
var bufView = new Uint16Array(buf);
if (bufView[0]===258) { // 258 === 0x0102
console.log("ok");
}
bufView[0] = 255; // buf now contains the bytes [0xFF, 0x00, 0x03, 0x07]
bufView[0] = 0xff05; // buf now contains the bytes [0x05, 0xFF, 0x03, 0x07]
bufView[1] = 0x0210; // buf now contains the bytes [0x05, 0xFF, 0x10, 0x02]
ArrayBuffer に関する一般的な実践的な質問の 1 つは、String
を ArrayBuffer
に変換する方法とその逆です。ArrayBuffer は実際にはバイト配列であるため、この変換では、文字列内の文字をバイトとして表す方法について両端で合意する必要があります。この「契約」は、文字列の文字エンコードです(通常の「契約条項」は、Unicode UTF-16 や iso8859-1 などです)。したがって、お客様と相手方が UTF-16 エンコードに同意している場合、変換コードは次のようになります。
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint16Array(buf));
}
function str2ab(str) {
var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
Uint16Array
の使用に注意してください。これは、ArrayBuffer のバイト数を 16 ビット要素としてアライメントする ArrayBuffer ビューです。文字エンコード自体は処理しません。これは String.fromCharCode
と str.charCodeAt
によって Unicode として処理されます。
StackOverflow のこの問題に関するよくある質問には、変換に関するやや複雑な解決策が記載された、高評価の回答があります。変換元として機能する FileReader
を作成し、文字列を含む Blob
をそれにフィードします。この方法は機能しますが、可読性が低く、遅いと思われます。根拠のない疑惑が人類の歴史において多くの間違いを引き起こしてきたため、ここではより科学的なアプローチをとることにしましょう。2 つのメソッドを jsperf でテストした結果、私の疑念が確認されました。デモはこちらで確認できます。
Chrome 20 では、この記事の直接 ArrayBuffer
操作コードを使用すると、FileReader
/Blob
メソッドを使用する場合と比べてほぼ 27 倍高速になります。