Comment append des données binarys à un tampon dans node.js

J’ai un tampon avec des données binarys:

var b = new Buffer ([0x00, 0x01, 0x02]); 

et je veux append 0x03 .

Comment puis-je append plus de données binarys? Je cherche dans la documentation mais pour append des données, il doit s’agir d’une chaîne, sinon une erreur se produit ( TypeError: l’argument doit être une chaîne ):

 var b = new Buffer (256); b.write ("hola"); console.log (b.toSsortingng ("utf8", 0, 4)); //hola b.write (", adios", 4); console.log (b.toSsortingng ("utf8", 0, 11)); //hola, adios 

Ensuite, la seule solution que je peux voir ici consiste à créer un nouveau tampon pour chaque donnée binary ajoutée et à le copier dans le tampon principal avec le décalage correct:

 var b = new Buffer (4); //4 for having a nice printed buffer, but the size will be 16KB new Buffer ([0x00, 0x01, 0x02]).copy (b); console.log (b); // new Buffer ([0x03]).copy (b, 3); console.log (b); // 

Mais cela semble un peu inefficace car je dois instancier un nouveau tampon pour chaque append.

Connaissez-vous un meilleur moyen d’append des données binarys?

MODIFIER

J’ai écrit un BufferedWriter qui écrit des octets dans un fichier en utilisant des tampons internes. Identique à BufferedReader mais pour l’écriture.

Un exemple rapide:

 //The BufferedWriter truncates the file because append == false new BufferedWriter ("file") .on ("error", function (error){ console.log (error); }) //From the beginning of the file: .write ([0x00, 0x01, 0x02], 0, 3) //Writes 0x00, 0x01, 0x02 .write (new Buffer ([0x03, 0x04]), 1, 1) //Writes 0x04 .write (0x05) //Writes 0x05 .close (); //Closes the writer. A flush is implicitly done. //The BufferedWriter appends content to the end of the file because append == true new BufferedWriter ("file", true) .on ("error", function (error){ console.log (error); }) //From the end of the file: .write (0xFF) //Writes 0xFF .close (); //Closes the writer. A flush is implicitly done. //The file contains: 0x00, 0x01, 0x02, 0x04, 0x05, 0xFF 

DERNIÈRE MISE À JOUR

Utilisez concat .

Réponse mise à jour pour Node.js ~> 0.8

Node est capable de concaténer des tampons tout seul maintenant.

 var newBuffer = Buffer.concat([buffer1, buffer2]); 

Ancienne réponse pour Node.js ~ 0.6

J’utilise un module pour append une fonction .concat , entre autres:

https://github.com/coolaj86/node-bufferjs

Je sais que ce n’est pas une solution “pure”, mais ça marche très bien pour mes besoins.

Les tampons sont toujours de taille fixe, il n’existe aucun moyen de les redimensionner dynamicment, de sorte que votre façon de les copier dans un tampon plus grand est la seule solution.

Cependant, pour être plus efficace, vous pouvez rendre le tampon plus grand que le contenu original, il contient donc un espace “libre” où vous pouvez append des données sans réaffecter le tampon. De cette façon, vous n’avez pas besoin de créer un nouveau tampon et de copier le contenu sur chaque opération d’ajout.

C’est pour aider ceux qui viennent ici à la recherche d’une solution qui demande une approche pure. Je recommande de comprendre ce problème car il peut se produire dans de nombreux endroits différents, pas seulement avec un object JS Buffer. En comprenant pourquoi le problème existe et comment le résoudre, vous améliorerez votre capacité à résoudre d’autres problèmes à l’avenir, car celui-ci est fondamental.

Pour ceux d’entre nous qui doivent faire face à ces problèmes dans d’autres langages, il est tout à fait naturel de concevoir une solution, mais il y a des gens qui ne réalisent pas comment éliminer les complexités et implémenter un tampon dynamic généralement efficace. Le code ci-dessous peut être optimisé.

J’ai laissé la méthode de lecture non implémentée pour que l’exemple rest petit.

La fonction realloc en C (ou tout langage traitant des allocations insortingnsèques) ne garantit pas que la taille de l’allocation sera étendue sans déplacer les données existantes – bien que cela soit parfois possible. Par conséquent, la plupart des applications ayant besoin de stocker une quantité inconnue de données utiliseront une méthode comme ci-dessous et ne réaffecteront pas constamment, sauf si la réallocation est très rare. C’est essentiellement la manière dont la plupart des systèmes de fichiers gèrent l’écriture de données dans un fichier. Le système de fichiers alloue simplement un autre nœud et maintient tous les nœuds liés, et lorsque vous lisez à partir de ce nœud, la complexité est réduite de sorte que le fichier / tampon semble être un tampon contigu unique.

Pour ceux d’entre vous qui souhaitent comprendre la difficulté de fournir simplement un tampon dynamic haute performance, il suffit de voir le code ci-dessous, et de faire des recherches sur les algorithmes de mémoire de mémoire et sur le tas de mémoire pour les programmes.

La plupart des langues fournissent un tampon de taille fixe pour des raisons de performances, puis fournissent une autre version de taille dynamic. Certains systèmes linguistiques optent pour un système tiers où ils conservent des fonctionnalités minimales (dissortingbution principale) et encouragent les développeurs à créer des bibliothèques pour résoudre des problèmes supplémentaires ou de niveau supérieur. C’est pourquoi vous pouvez vous demander pourquoi une langue ne fournit pas certaines fonctionnalités. Cette petite fonctionnalité permet de réduire les coûts de maintenance et d’amélioration du langage, mais vous devez écrire vos propres implémentations ou dépendre d’un tiers.

 var Buffer_A1 = function (chunk_size) { this.buffer_list = []; this.total_size = 0; this.cur_size = 0; this.cur_buffer = []; this.chunk_size = chunk_size || 4096; this.buffer_list.push(new Buffer(this.chunk_size)); }; Buffer_A1.prototype.writeByteArrayLimited = function (data, offset, length) { var can_write = length > (this.chunk_size - this.cur_size) ? (this.chunk_size - this.cur_size) : length; var lastbuf = this.buffer_list.length - 1; for (var x = 0; x < can_write; ++x) { this.buffer_list[lastbuf][this.cur_size + x] = data[x + offset]; } this.cur_size += can_write; this.total_size += can_write; if (this.cur_size == this.chunk_size) { this.buffer_list.push(new Buffer(this.chunk_size)); this.cur_size = 0; } return can_write; }; /* The `data` parameter can be anything that is array like. It just must support indexing and a length and produce an acceptable value to be used with Buffer. */ Buffer_A1.prototype.writeByteArray = function (data, offset, length) { offset = offset == undefined ? 0 : offset; length = length == undefined ? data.length : length; var rem = length; while (rem > 0) { rem -= this.writeByteArrayLimited(data, length - rem, rem); } }; Buffer_A1.prototype.readByteArray = function (data, offset, length) { /* If you really wanted to implement some read functionality then you would have to deal with unaligned reads which could span two buffers. */ }; Buffer_A1.prototype.getSingleBuffer = function () { var obuf = new Buffer(this.total_size); var cur_off = 0; var x; for (x = 0; x < this.buffer_list.length - 1; ++x) { this.buffer_list[x].copy(obuf, cur_off); cur_off += this.buffer_list[x].length; } this.buffer_list[x].copy(obuf, cur_off, 0, this.cur_size); return obuf; };