NodeJSバイナリバッファーをJavaScript ArrayBufferに変換するにはどうすればよいですか?
Buffer
のインスタンスはUint8Array
のインスタンスでもあります node.js 4.x以降では。したがって、最も効率的なソリューションは、 https://stackoverflow.com/a/31394257/1375574 に従って、buf.buffer
プロパティに直接アクセスすることです。他の方向に進む必要がある場合、BufferコンストラクターはArrayBufferView引数も取ります。
これはコピーを作成しないことに注意してください。つまり、ArrayBufferViewに書き込むと、元のBufferインスタンスに書き込みが行われます。
バッファーからArrayBufferへ:
function toArrayBuffer(buf) {
var ab = new ArrayBuffer(buf.length);
var view = new Uint8Array(ab);
for (var i = 0; i < buf.length; ++i) {
view[i] = buf[i];
}
return ab;
}
ArrayBufferからバッファへ:
function toBuffer(ab) {
var buf = Buffer.alloc(ab.byteLength);
var view = new Uint8Array(ab);
for (var i = 0; i < buf.length; ++i) {
buf[i] = view[i];
}
return buf;
}
バッファーはUint8Arrayであるため、ArrayBufferにアクセスするだけです。これはO(1):
// node buffer
var b = new Buffer(512);
// ArrayBuffer
var ab = b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength);
// TypedArray
var ui32 = new Uint32Array(b.buffer, b.byteOffset, b.byteLength / Uint32Array.BYTES_PER_ELEMENT);
slice
とoffset stuffはrequiredです。なぜなら、小さなバッファー(<4096バイト、私は思う)は共有ArrayBuffer上のビューだからです。これがないと、別のTypedArrayからのデータを含むArrayBufferになってしまう可能性があります。
Martin Thomson's answer を使用します。これはO(n)時間で実行されます。 (非最適化についての彼の答えに対するコメントへの私の回答も参照してください。DataViewの使用は遅いです。バイトを反転する必要がある場合でも、それを行うより速い方法があります。)
https://www.npmjs.com/package/memcpy を使用して、どちらの方向にも移動できます(Buffer to ArrayBufferおよびback)。ここに投稿された他の回答よりも高速で、よく書かれたライブラリです。 Node 0.12〜iojs 3.xには、ngossenのフォークが必要です( this を参照)。
「ArrayBufferからバッファへ」は次の方法で実行できます。
var buffer = Buffer.from( new Uint8Array(ab) );
より簡単な書き方
var arrayBuffer = new Uint8Array(nodeBuffer).buffer;
ただし、これは、1024個の要素を持つバッファーで推奨されるtoArrayBuffer関数よりも約4倍遅いように見えます。
次の優れたnpmパッケージを使用してください: to-arraybuffer
。
または、自分で実装することもできます。バッファの名前がbuf
の場合、これを実行します。
buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength)
ArrayBuffer
は、型付きのBuffer
と考えることができます。
したがって、ArrayBuffer
には常に型が必要です(いわゆる「配列バッファービュー」)。通常、Array Buffer ViewのタイプはUint8Array
またはUint16Array
です。
ArrayBufferとString間の変換 にRenato Manginiからの良い記事があります。
コード例で重要な部分を要約しました(Node.jsの場合)。また、型付きArrayBuffer
と型なしBuffer
の間の変換方法も示します。
function stringToArrayBuffer(string) {
const arrayBuffer = new ArrayBuffer(string.length);
const arrayBufferView = new Uint8Array(arrayBuffer);
for (let i = 0; i < string.length; i++) {
arrayBufferView[i] = string.charCodeAt(i);
}
return arrayBuffer;
}
function arrayBufferToString(buffer) {
return String.fromCharCode.apply(null, new Uint8Array(buffer));
}
const helloWorld = stringToArrayBuffer('Hello, World!'); // "ArrayBuffer" (Uint8Array)
const encodedString = new Buffer(helloWorld).toString('base64'); // "string"
const decodedBuffer = Buffer.from(encodedString, 'base64'); // "Buffer"
const decodedArrayBuffer = new Uint8Array(decodedBuffer).buffer; // "ArrayBuffer" (Uint8Array)
console.log(arrayBufferToString(decodedArrayBuffer)); // prints "Hello, World!"
Float64Arrayに対して上記を試しましたが、うまくいきませんでした。
私は、データを正しいチャンクで「INTO」ビューに読み込む必要があることに気付きました。これは、ソースバッファから一度に8バイトを読み取ることを意味します。
とにかく、これは私が終わったものです...
var buff = new Buffer("40100000000000004014000000000000", "hex");
var ab = new ArrayBuffer(buff.length);
var view = new Float64Array(ab);
var viewIndex = 0;
for (var bufferIndex=0;bufferIndex<buff.length;bufferIndex=bufferIndex+8) {
view[viewIndex] = buff.readDoubleLE(bufferIndex);
viewIndex++;
}
このプロキシは、バッファをコピーせずにTypedArrayのいずれかとして公開します。 :
https://www.npmjs.com/package/node-buffer-as-typedarray
LEでのみ動作しますが、BEに簡単に移植できます。また、これがどれほど効率的かを実際にテストすることもありません。