1。オープニング分析
いわゆるバッファーバッファーは、「一時的な保管エリア」を意味します。これは、入力データと出力データを一時的に保存するメモリです。
JS言語自体には、文字列データ型のみがあり、バイナリデータ型はありません。したがって、nodejsは、バイナリデータの操作を提供するためにピアツーストリングであるグローバルコンストラクターバッファーを提供します。ファイルを読み取ってバッファインスタンスを取得することに加えて、たとえば次のように直接構築することもできます。
コードコピーは次のとおりです。
varバッファー=新しいバッファー([0x68、0x65、0x6c、0x6c、0x6f]);
バッファーは文字列に似ています。 .length属性を使用してバイトの長さを取得することに加えて、[インデックス]メソッドを使用して、指定された位置でバイトを読み取ることもできます。
コードコピーは次のとおりです。
バッファー[0]; // 0x68;
バッファと文字列は互いに変換できます。たとえば、バイナリデータは、指定されたエンコードを使用して文字列に変換できます。
コードコピーは次のとおりです。
var str = buffer.tostring( "utf-8"); // こんにちは
指定されたエンコードの下で文字列をバイナリデータに変換します。
コードコピーは次のとおりです。
var buffer = new Buffer( "hello"、 "utf-8"); // <バッファ68 65 6c 6c 6f>
少し違い:
バッファーと文字列には重要な違いがあります。文字列は読み取り専用であり、文字列の変更は新しい文字列になり、元の文字列は変更されません。
バッファーに関しては、ポインター操作を行うことができるC言語アレイのようなものです。たとえば、特定の位置のバイトは[インデックス]メソッドで直接変更できます。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
スライス法は新しいバッファを返すのではなく、以下に示すように、元のバッファの中央にある場所へのポインターを返します。
[0x68、0x65、0x6c、0x6c、0x6f]
^ ^
| |
bin bin.slice(2)
したがって、スライス法によって返されるバッファーの変更は、例えば、元のバッファに作用します。
コードコピーは次のとおりです。
varバッファー=新しいバッファー([0x68、0x65、0x6c、0x6c、0x6f]);
var sub = bin.slice(2);
sub [0] = 0x65;
console.log(バッファー); // <バッファ68 65 65 6c 6f>
バッファをコピーする場合は、まず新しいバッファーを作成し、.Copyメソッドを使用して元のバッファーのデータをコピーする必要があります。
これは、新しいメモリを適用し、既存のメモリのデータをコピーすることに似ています。これが例です。
コードコピーは次のとおりです。
varバッファー=新しいバッファー([0x68、0x65、0x6c、0x6c、0x6f]);
var dup = new Buffer(bin.length);
buffer.copy(dup);
dup [0] = 0x48;
console.log(バッファー); // <バッファ68 65 6c 6c 6f>
console.log(dup); // <バッファー48 65 65 6c 6f>
要するに、バッファーはJSのデータ処理機能を文字列から任意のバイナリデータに拡張します。
上記では、バッファーが何であるかを簡単に理解できます。使用方法と以下の特定の使用シナリオについて説明しましょう。
第二に、バッファーについて話します
JavaScriptは文字列処理に非常に優しいものであり、広いバイトまたは単一のバイト文字列であろうと、文字列と見なされます。ノードは、ネットワークプロトコルを処理し、データベースを操作し、画像を処理する、ファイルアップロードなどを処理する必要があり、大量のバイナリデータを処理する必要があります。それらに付属する文字列は、これらの要件を満たすことにはほど遠いので、バッファーが生まれました。
バッファ構造
バッファーは、JavaScriptとC ++を組み合わせた典型的なモジュールです。パフォーマンス関連部品はC ++で実装され、非パフォーマンス関連部品はJavaScriptに実装されます。
プロセスが開始されてグローバルオブジェクトに配置されると、ノードはメモリにインストールされるため、要求する必要はありません。
バッファオブジェクト:配列と同様に、その要素は16進数の2桁です。
バッファメモリの割り当て
バッファオブジェクトのメモリ割り当ては、V8のヒープメモリにはありませんが、ノードのC ++レベルでメモリアプリケーションを実装します。
メモリアプリケーションを効率的に使用するために、ノードはスラブ割り当てメカニズムを使用します。これは、さまざまな *nixオペレーティングシステムを適用する動的メモリ管理メカニズムです。スラブには3つの状態があります。
(1)完全:完全に割り当てられた状態
(2)部分的:部分的な割り当てステータス
(3)空:割り当てられていない状態
バッファ変換
バッファオブジェクトは文字列に変換でき、サポートされているエンコードタイプは次のとおりです。
ASCII、UTF-8、UTF-16LE/UCS-2、base64、バイナリ、六角
バッファーする文字列
新しいバッファー(STR、[エンコード])、デフォルトのUTF-8
buf.write(string、[offset]、[length]、[encoding])
弦からバッファー
buf.toString([encoding]、[start]、[end])
バッファーによってサポートされていないコーディングタイプ
buffer.isencoding(エンコード)によってそれをサポートするかどうかを判断する
iconv-lite:純粋なJavaScriptの実装、C ++からJavaScript変換なしのより軽い、より良いパフォーマンス
ICONV:C ++でlibiconvライブラリを呼び出すと完了します
バッファスプライシング
「res.on( 'data'、function(chunk){})」に注意してください。パラメーターチャンクはバッファオブジェクトです。 +ステッチを直接使用すると、自動的に文字列に変換されます。広いバイト文字の場合、文字化けコードが発生する可能性があります。
解決:
(1)読み取り可能なストリームのsetEncoding()メソッドを介して、このメソッドにより、データイベントはバッファオブジェクトを渡すことができますが、エンコードされた文字列、およびストリンコダーモジュールは内部で使用されます。
(2)バッファオブジェクトを配列に保存し、最終的に大きなバッファーに組み立ててから、文字列出力にエンコードします。
バッファーはファイルI/OおよびネットワークI/Oで広く使用されており、そのパフォーマンスは非常に重要であり、通常の文字列のパフォーマンスよりもはるかに高くなっています。
パフォーマンスの文字列変換に加えて、バッファーを使用する場合、ファイルを読み取るときのパフォーマンスへの影響には、ハイウォーターマーク設定が重要です。
a。ハイウォーターマーク設定は、バッファメモリの割り当てと使用に特定の影響を与えます。
b。 Highwatermarkの設定が小さすぎるため、システム呼び出しが多すぎる可能性があります。
バッファーを使用する必要があるとき、使用しない場合はいつ-------純粋なJavaScriptはUnicodeコードをサポートしますが、バイナリをサポートしません。 TCPストリームまたはファイルストリームを解く場合、ストリームを処理する必要があります。非UTF-8文字列、バイナリ、その他の形式を保存する場合、「バッファ」を使用する必要があります。
3.例を紹介します
コードコピーは次のとおりです。
var buf = new Buffer( "これはテキストコンカットテスト!")、str = "これはテキストコンカットテストです!" ;
Console.time( "バッファーコンカットテスト!");
var list = [];
var len = 100000 * buf.length;
for(var i = 0; i <100000; i ++){
list.push(buf);
len += buf.length;
}
var s1 = buffer.concat(list、len).toString();
Console.TimeEnd( "バッファーコンカットテスト!");
Console.time( "String concat Test!");
var list = [];
for(var i = 100000; i> = 0; i-){
list.push(str);
}
var s2 = list.join( "");
Console.TimeEnd( "String Concat Test!");
以下は実行中の結果です。
読み取り速度は間違いなく高速であり、バッファーにはtoString()の動作も必要です。したがって、文字列を保存する場合でも、文字列を使用する必要があります。文字列に文字列を大きな弦にスプライスしたとしても、弦の速度はバッファーよりも遅くなりません。
では、いつバッファーを使用する必要があるのでしょうか?方法がない場合、UTF-8以外の文字列、バイナリ、その他の形式を保存する場合、それらを使用する必要があります。
4つ、要約しましょう
(1)JavaScriptはUnicodeエンコードデータの処理に適していますが、バイナリデータの処理には友好的ではありません。
(2)、したがって、TCPストリームまたはファイルシステムを処理する場合、オクテットストリームを処理する必要があります。
(3)、ノードには、オクテットストリームを処理、作成、および消費する方法がいくつかあります。
(4)生データはバッファインスタンスに保存されます。バッファーは整数アレイに似ていますが、そのメモリはV8スタックの外側に割り当てられます。バッファーのサイズを変更することはできません。
(5)、処理されたエンコーディングタイプは、ASCII、UTF8、UTF16LE、UCS2(UTF16LEのエイリアス)、Base64、バイナリ、HEXです。
(6)バッファーはグローバル要素であり、バッファーインスタンスは直接新しいバッファー()によって取得されます。