如何将二进制数据追加到node.js中的缓冲区中

最后更新

使用concat 。

编辑

我写了一个使用内部缓冲区将字节写入文件的BufferedWriter 。 与BufferedReader相同,但用于写入。

一个简单的例子:

//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 

原文问题

我有一些二进制数据的缓冲区:

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

我想追加0x03

我怎样才能附加更多的二进制数据? 我正在search的文件,但附加数据必须是一个string,如果没有,发生错误( TypeError:参数必须是一个string ):

 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 

然后,我可以在这里看到的唯一解决scheme是为每个附加的二进制数据创build一个新的缓冲区,并用正确的偏移量将其复制到主缓冲区:

 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> 

但是这似乎有点低效,因为我必须为每个追加实例化一个新的缓冲区。

你知道一个更好的方法来追加二进制数据吗?

Node.js更新的答案〜> 0.8

节点现在可以自行连接缓冲区 。

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

Node.js的旧答案〜0.6

我使用一个模块来添加.concatfunction,其中包括:

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

我知道这不是一个“纯粹的”解决scheme,但它对我的目的非常有效。

缓冲区总是固定的大小,没有固定的方式来dynamic调整它们,所以你的方法将其复制到更大的缓冲区是唯一的方法。

但是,为了提高效率,可以使缓冲区大于原始内容,因此它包含一些“空闲”空间,您可以在不重新分配缓冲区的情况下添加数据。 这样你不需要创build一个新的缓冲区,并复制每个附加操作的内容。

这是为了帮助来到这里的人寻找一种想要纯粹的方法的解决scheme。 我会build议理解这个问题,因为它可能发生在许多不同的地方,而不只是一个JS缓冲区对象。 通过理解问题存在的原因以及如何解决问题,你将提高解决未来其他问题的能力,因为这个问题是如此重要。

对于那些不得不用其他语言来解决这些问题的人来说,devise一个解决scheme是很自然的,但是有些人可能没有意识到如何去除复杂性,实现一个通常有效的dynamic缓冲。 下面的代码可能有进一步优化的潜力。

我已经没有实现读取方法,以保持这个例子的大小。

C中的realloc函数(或任何处理内在分配的语言)并不能保证分配的大小不会随着现有数据的移动而扩大 – 尽pipe有时是可能的。 因此,大多数应用程序在需要存储未知数量的数据时,将使用类似下面的方法,而不是经常重新分配,除非重新分配非常less。 这基本上是大多数文件系统处理将数据写入文件的方式。 文件系统只是简单地分配另一个节点,并将所有节点连接在一起,当你从中读取时,复杂度被抽象出来,这样文件/缓冲区看起来就是一个连续的缓冲区。

对于那些希望了解简单提供高性能dynamic缓冲区的人来说,只需要查看下面的代码,还可以对内存堆algorithm以及内存堆如何工作。

大多数语言都会提供一个固定大小的缓冲区以提高性能,然后提供另一个dynamic大小的版本。 有些语言系统select第三方系统,使核心function保持最小(核心分发),并鼓励开发人员创build库来解决更多或更高级别的问题。 这就是为什么你可能会质疑为什么一种语言不提供某些function。 这个小的核心function可以降低维护和增强语言的成本,但是最终不得不编写自己的实现或者依赖于第三方。

 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; };