node.js - nodejs - read a buffer node
Cómo anexar datos binarios a un búfer en node.js (3)
Tengo un buffer con algunos datos binarios:
var b = new Buffer ([0x00, 0x01, 0x02]);
y quiero agregar 0x03
.
¿Cómo puedo agregar más datos binarios? Estoy buscando en la documentación pero para anexar datos debe ser una cadena, si no, se produce un error ( TypeError: Argument debe ser una cadena ):
var b = new Buffer (256);
b.write ("hola");
console.log (b.toString ("utf8", 0, 4)); //hola
b.write (", adios", 4);
console.log (b.toString ("utf8", 0, 11)); //hola, adios
Entonces, la única solución que puedo ver aquí es crear un nuevo buffer para cada dato binario adjunto y copiarlo al buffer principal con el offset correcto:
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); //<Buffer 00 01 02 00>
new Buffer ([0x03]).copy (b, 3);
console.log (b); //<Buffer 00 01 02 03>
Pero esto parece un poco ineficiente porque tengo que crear una instancia de un nuevo buffer para cada apéndice.
¿Conoces una mejor manera de anexar datos binarios?
EDITAR
BufferedWriter un BufferedWriter que escribe bytes en un archivo usando búferes internos. Igual que BufferedReader pero para escribir.
Un ejemplo rápido:
//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
ÚLTIMA ACTUALIZACIÓN
Use concat .
Respuesta actualizada para Node.js ~> 0.8
Nodo es capaz de concat por sí solo ahora.
var newBuffer = Buffer.concat([buffer1, buffer2]);
Vieja respuesta para Node.js ~ 0.6
Utilizo un módulo para agregar una función .concat
, entre otros:
https://github.com/coolaj86/node-bufferjs
Sé que no es una solución "pura", pero funciona muy bien para mis propósitos.
Esto es para ayudar a cualquiera que venga aquí a buscar una solución que quiera un enfoque puro. Yo recomendaría entender este problema porque puede suceder en muchos lugares diferentes, no solo con un objeto JS Buffer. Al comprender por qué existe el problema y cómo resolverlo, mejorará su capacidad para resolver otros problemas en el futuro, ya que este es tan fundamental.
Para aquellos de nosotros que tenemos que lidiar con estos problemas en otros idiomas, es bastante natural idear una solución, pero hay personas que pueden no darse cuenta de cómo abstraer las complejidades e implementar un buffer dinámico generalmente eficiente. El código a continuación puede tener potencial para optimizarse aún más.
Dejé el método de lectura sin implementar para mantener el tamaño pequeño del ejemplo.
La función realloc
en C (o cualquier lenguaje que trate con asignaciones intrínsecas) no garantiza que la asignación se amplíe en tamaño sin mover los datos existentes, aunque a veces es posible. Por lo tanto, la mayoría de las aplicaciones que necesiten almacenar una cantidad desconocida de datos utilizarán un método como el siguiente y no se reasignarán constantemente, a menos que la reasignación sea muy poco frecuente. Esta es esencialmente la forma en que la mayoría de los sistemas de archivos manejan la escritura de datos en un archivo. El sistema de archivos simplemente asigna otro nodo y mantiene todos los nodos vinculados entre sí, y cuando lee de él, la complejidad se abstrae para que el archivo / búfer parezca ser un único búfer contiguo.
Para aquellos de ustedes que desean comprender la dificultad de simplemente proporcionar un búfer dinámico de alto rendimiento, solo necesitan ver el código a continuación, y también investigar sobre los algoritmos del montón de memoria y cómo funciona el montón de memoria para los programas.
La mayoría de los lenguajes proporcionará un búfer de tamaño fijo por motivos de rendimiento, y luego proporcionará otra versión que sea de tamaño dinámico. Algunos sistemas de idiomas optan por un sistema de terceros donde mantienen la funcionalidad básica mínima (distribución central) y alientan a los desarrolladores a crear bibliotecas para resolver problemas adicionales o de mayor nivel. Es por eso que puede preguntar por qué un idioma no proporciona alguna funcionalidad. Esta pequeña funcionalidad central permite reducir los costos al mantener y mejorar el idioma, sin embargo, termina teniendo que escribir sus propias implementaciones o dependiendo de un tercero.
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;
};
Los búferes son siempre de tamaño fijo, no hay una forma integrada de redimensionarlos dinámicamente, por lo que su método de copiarlo en un búfer más grande es la única forma.
Sin embargo, para ser más eficiente, puede hacer que el Buffer sea más grande que el contenido original, por lo que contiene un espacio "libre" donde puede agregar datos sin reasignar el Buffer. De esta forma no es necesario crear un nuevo Buffer y copiar el contenido en cada operación de adición.