Comment convertir un tampon binaire NodeJS en JavaScript ArrayBuffer?
Les instances de Buffer
sont également des instances de Uint8Array
dans node.js 4.x et versions ultérieures. Ainsi, la solution la plus efficace consiste à accéder directement à la propriété buf.buffer
, conformément à https://stackoverflow.com/a/31394257/1375574 . Le constructeur Buffer prend également un argument ArrayBufferView si vous devez aller dans l'autre sens.
Notez que cela ne créera pas de copie, ce qui signifie que les écritures sur n'importe quel ArrayBufferView seront écrites sur l'instance de tampon d'origine.
De 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;
}
De ArrayBuffer à Buffer:
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;
}
Les tampons sont des Uint8Arrays, il vous suffit donc d'accéder à son ArrayBuffer. C'est 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);
Les options slice
et offset sont required car les petits tampons (<4096 octets, je pense) sont des vues sur un ArrayBuffer partagé. Sans cela, vous pourriez vous retrouver avec un ArrayBuffer contenant des données d'un autre TypedArray.
Utilisez la réponse de Martin Thomson , qui s'exécute dans le temps O(n). (Voir également mes réponses aux commentaires sur sa réponse concernant les non-optimisations. L'utilisation d'un DataView est lente. Même si vous devez retourner des octets, il existe des moyens plus rapides pour le faire.)
Vous pouvez utiliser https://www.npmjs.com/package/memcpy pour aller dans un sens ou dans l'autre (mémoire tampon vers ArrayBuffer et retour). C'est plus rapide que les autres réponses affichées ici et c'est une bibliothèque bien écrite. Les nœuds 0.12 à iojs 3.x nécessitent la fourchette de ngossen (voir this ).
"De ArrayBuffer à Buffer" pourrait être fait de cette façon:
var buffer = Buffer.from( new Uint8Array(ab) );
Un moyen plus rapide de l'écrire
var arrayBuffer = new Uint8Array(nodeBuffer).buffer;
Cependant, cela semble être environ 4 fois plus lent que la fonction suggérée toArrayBuffer sur un tampon de 1024 éléments.
Utilisez l'excellent paquet npm suivant: to-arraybuffer
.
Ou, vous pouvez l'implémenter vous-même. Si votre tampon s'appelle buf
, procédez comme suit:
buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength)
Vous pouvez imaginer une ArrayBuffer
comme une Buffer
dactylographiée.
Une ArrayBuffer
a donc toujours besoin d'un type (appelé "Array Buffer View"). Généralement, la vue Array Buffer View a le type Uint8Array
ou Uint16Array
.
Il y a un bon article de Renato Mangini sur la conversion entre un ArrayBuffer et un String .
J'ai résumé les parties essentielles dans un exemple de code (pour Node.js). Il montre également comment convertir une ArrayBuffer
typée et une Buffer
non typée.
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!"
J'ai essayé ce qui précède pour un Float64Array et cela n'a tout simplement pas fonctionné.
J'ai fini par me rendre compte que les données devaient être lues «dans la vue» par tranches correctes. Cela signifie lire 8 octets à la fois à partir du tampon source.
Quoi qu'il en soit, c'est ce que j'ai fini par ...
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++;
}
Ce proxy exposera le tampon sous la forme de n'importe lequel des TypedArrays, sans aucune copie. :
https://www.npmjs.com/package/node-buffer-as-typedarray
Cela ne fonctionne que sur LE, mais peut être facilement porté sur BE . En outre, jamais eu à tester l'efficacité de cela.