95

いくつかのバイナリデータを含むバッファがあります:

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

と追加したい0x03

どうすればバイナリデータを追加できますか?ドキュメントを検索していますが、データを追加するには文字列である必要があります。そうでない場合は、エラーが発生します(TypeError:引数は文字列である必要があります):

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

次に、ここで確認できる唯一の解決策は、追加されたバイナリデータごとに新しいバッファーを作成し、それを正しいオフセットでメジャーバッファーにコピーすることです。

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>

しかし、追加ごとに新しいバッファをインスタンス化する必要があるため、これは少し非効率的なようです。

バイナリデータを追加するためのより良い方法を知っていますか?

編集

内部バッファを使用してファイルにバイトを書き込む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

最後の更新

concatを使用します。

4

4 に答える 4

161

Node.jsの回答を更新〜> 0.8

ノードは、それ自体でバッファーを連結できるようになりました。

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

Node.jsの古い答え〜0.6

.concat特に、モジュールを使用して関数を追加します。

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

私はそれが「純粋な」解決策ではないことを知っていますが、それは私の目的には非常にうまく機能します。

于 2012-04-27T18:47:05.027 に答える
12

バッファは常に固定サイズであり、動的にサイズを変更する方法は組み込まれていないため、より大きなバッファにコピーする方法が唯一の方法です。

ただし、より効率的にするには、バッファを元のコンテンツよりも大きくすることができるため、バッファを再割り当てせずにデータを追加できる「空き」スペースが含まれています。そうすれば、新しいバッファを作成して、各追加操作で内容をコピーする必要はありません。

于 2012-04-27T18:41:06.870 に答える
8

これは、純粋なアプローチを必要とするソリューションを探してここに来る人を助けるためです。この問題は、JS Bufferオブジェクトだけでなく、さまざまな場所で発生する可能性があるため、理解することをお勧めします。問題が存在する理由とその解決方法を理解することで、これは非常に基本的な問題であるため、将来的に他の問題を解決する能力が向上します。

他の言語でこれらの問題に対処しなければならない私たちにとって、解決策を考案するのは非常に自然ですが、複雑さを抽象化して一般的に効率的な動的バッファーを実装する方法を理解していない人もいます。以下のコードは、さらに最適化される可能性があります。

例のサイズを小さく保つために、readメソッドは実装されていません。

reallocC(または固有の割り当てを処理する言語)の関数は、既存のデータを移動せずに割り当てのサイズが拡張されることを保証しません-場合によっては可能ですが。したがって、不明な量のデータを格納する必要がある場合のほとんどのアプリケーションは、再割り当ての頻度が非常に低い場合を除いて、以下のような方法を使用し、常に再割り当てするわけではありません。これは基本的に、ほとんどのファイルシステムがファイルへのデータの書き込みを処理する方法です。ファイルシステムは、単に別のノードを割り当て、すべてのノードをリンクしたままにします。ファイルシステムから読み取ると、複雑さが抽象化され、ファイル/バッファーが単一の連続したバッファーのように見えます。

単に高性能の動的バッファを提供することの難しさを理解したい場合は、以下のコードを表示するだけで、メモリヒープアルゴリズムとプログラムでのメモリヒープの動作について調査する必要があります。

ほとんどの言語は、パフォーマンス上の理由から固定サイズのバッファーを提供し、次にサイズが動的な別のバージョンを提供します。一部の言語システムは、コア機能を最小限に抑え(コア配布)、開発者に追加またはより高いレベルの問題を解決するためのライブラリを作成するように促すサードパーティシステムを選択します。これが、言語が一部の機能を提供しない理由を疑問視する理由です。この小さなコア機能により、言語の維持と拡張のコストを削減できますが、最終的には独自の実装を作成するか、サードパーティに依存することになります。

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;
};
于 2015-08-20T12:51:26.267 に答える
0

特定の場所にバイトを挿入します。

insertToArray(arr,index,item) {
   return Buffer.concat([arr.slice(0,index),Buffer.from(item,"utf-8"),arr.slice(index)]);
}
于 2020-03-31T11:38:12.503 に答える