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

如何在node.js中将二进制数据附加到缓冲区,node.js,binary,append,buffer,Node.js,Binary,Append,Buffer,我有一个包含一些二进制数据的缓冲区: var b = new Buffer ([0x00, 0x01, 0x02]); 我想附加0x03 如何附加更多的二进制数据?我正在文档中搜索,但对于附加数据,它必须是字符串,如果不是,则会发生错误(TypeError:参数必须是字符串): 然后,我在这里看到的唯一解决方案是为每个附加的二进制数据创建一个新的缓冲区,并使用正确的偏移量将其复制到主缓冲区: var b = new Buffer (4); //4 for having a nice print

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

var b = new Buffer ([0x00, 0x01, 0x02]);
我想附加
0x03

如何附加更多的二进制数据?我正在文档中搜索,但对于附加数据,它必须是字符串,如果不是,则会发生错误(TypeError:参数必须是字符串):

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

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的旧答案 我使用一个模块添加一个
.concat
函数,其中包括:


我知道这不是一个“纯”的解决方案,但就我的目的而言,它工作得非常好。

这是为了帮助任何来这里寻找纯方法解决方案的人。我建议理解这个问题,因为它可能发生在很多不同的地方,而不仅仅是JS缓冲区对象。通过理解问题存在的原因以及如何解决它,你将提高你在未来解决其他问题的能力,因为这是一个非常基本的问题

对于我们这些必须用其他语言处理这些问题的人来说,设计一个解决方案是很自然的,但是有些人可能没有意识到如何抽象出复杂性并实现一个普遍有效的动态缓冲区。下面的代码可能需要进一步优化

为了保持示例的小规模,我没有实现read方法

C(或任何处理内部分配的语言)中的
realloc
函数不能保证在不移出现有数据的情况下扩展分配的大小,尽管有时是可能的。因此,当需要存储未知数量的数据时,大多数应用程序将使用如下方法,而不是不断地重新分配,除非重新分配非常罕见。这就是大多数文件系统处理向文件写入数据的基本方式。文件系统只需分配另一个节点,并将所有节点链接在一起,当您从中读取时,复杂性被抽象掉,因此文件/缓冲区似乎是一个连续的缓冲区

对于那些希望理解仅仅提供高性能动态缓冲区的困难的人,您只需要查看下面的代码,还需要对内存堆算法以及内存堆如何为程序工作进行一些研究

出于性能原因,大多数语言将提供一个固定大小的缓冲区,然后提供另一个大小动态的版本。一些语言系统选择第三方系统,在第三方系统中,它们将核心功能最小化(核心分发),并鼓励开发人员创建库来解决其他或更高级别的问题。这就是为什么您可能会质疑为什么一种语言不提供某些功能。这种小型核心功能可以降低维护和增强该语言的成本,但最终需要编写自己的实现或依赖第三方

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;
};
var Buffer\u A1=函数(块大小){
this.buffer_list=[];
此值为0.total_size=0;
此.cur_size=0;
this.cur_buffer=[];
this.chunk_size=chunk|u size | 4096;
this.buffer_list.push(新缓冲区(this.chunk_大小));
};
Buffer_A1.prototype.writeByteArrayLimited=函数(数据、偏移量、长度){
var can\u write=length>(this.chunk\u size-this.cur\u size)?(this.chunk\u size-this.cur\u size):长度;
var lastbuf=this.buffer_list.length-1;
对于(变量x=0;x0){
rem-=this.writeByteArrayLimited(数据,长度-rem,rem);
}
};
Buffer_A1.prototype.readByteArray=函数(数据、偏移量、长度){
/*
如果您真的想实现一些读取功能
然后您必须处理未对齐的读取,这可能会导致
跨越两个缓冲区。
*/
};
Buffer_A1.prototype.getSingleBuffer=函数(){
var obuf=新缓冲区(此.total_大小);
var cur_off=0;
var x;
对于(x=0;x
将字节插入特定位置

insertToArray(arr,index,item) {
   return Buffer.concat([arr.slice(0,index),Buffer.from(item,"utf-8"),arr.slice(index)]);
}

concat
函数与我发布的功能完全相同:(.它计算de total length,然后复制调整偏移量的所有缓冲区的数据。这就是它的工作方式。正如@stewe所指出的,缓冲区被实例化为固定大小,这是由于内存分配的方式。但是在c中,我们有realloc函数在必要时动态扩展内存。node.js应该知道这一点。@Gabriella妈妈,我推荐Subm
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;
};
insertToArray(arr,index,item) {
   return Buffer.concat([arr.slice(0,index),Buffer.from(item,"utf-8"),arr.slice(index)]);
}