Node.js-bufferの接合問題に注意
29896 ワード
最近出会った昔出会っていない罠は、dataの中のchunkのつなぎです.本人がフロントエンドエンジニアであるため、bufferの概念に対する認識が不足している.今度のシーンはhttpを通るのです.getは遠位端のウェブページファイルをキャプチャし、うっかり相手のファイル符号化はgbk(古いJava環境での解決策と推定される)であり、私の地元のコードはutf 8の符号化であり、最終的には2つの部分のコードを統合してクライアントに出力する必要があるので、私は受け入れた部分をトランスコードする必要があり、トランスコードはiconvで実現する必要がある.その前に受け取ったchunkを組み立てる必要があります.次は私の最も原始的な組み立て方法です.私の概念の中で彼らをstringとして組み立てたからです.
残念ながら、私は呼び出します.
ELSEQ異常が放出されます.その理由は、2つのchunk(Bufferオブジェクト)の接合が正常ではなく、bufferが行うことに相当するからである.toString() + buffer.toString().bufferが完全でない場合、toStringが出た後のstringには問題があります(例えば、中文字が切断されています).このように出てきたstringはiconvに正常にトランスコードされません.では、正しいつなぎ合わせはどうでしょうか.大神兼好基友@Python発烧友の助けの下で、以下のコードが正しいです.
このときのdataこそ正しいbufferオブジェクトです.
しかし、データを受信するには、このようなシーンは非常に一般的なシーンであるべきで、毎回このようなコードをたくさん書くのは、本当に手間がかかります.では、パッケージを再構築しましょう.
ここには2つのプライベートメソッドがあります.concatと_toBuffer.その目的は,各メソッドの職責が単一であることを保証し,CPUを無駄にしないようにtoBufferに状態設定を行うことである.次の呼び出しはとても簡単です.
コード量がかなり少なく,第1の方法の使用とほぼ同じであることがわかる.うん、さりげなく自慢して、さっぱり:).また、上記のコードは直接requireであることがわかります.
その理由は、npm install bufferhelperで直接できるNPMに公開したからです.プロジェクトアドレスはgithubにあります.https://github.com/JacksonTian/bufferhelper
最後にこのlibはまだユニットテストを書いていないので、圧力測定をして、後で追加します.最后に友达@Pythonの友达に感谢します.最後に、node-iconvの著者はツールセットも提供しています(https://github.com/bnoordhuis/node-buffertools)、一部はc/c++で完成していますが、私のニーズはそんなに複雑ではありません.最も簡単なconcatさえあれば満足できます.このbufferhelperは中国語の環境の下の同級生にとても役に立つと信じています.
ソース:https://cnodejs.org/topic/4faf65852e8fb5bc65113403
var data = "";
res.on('data', function (chunk) {
data += chunk;
})
.on("end", function () {
// data
});
残念ながら、私は呼び出します.
var iconv = new Iconv('GBK', 'UTF-8');
iconv.convert(data).toString();
ELSEQ異常が放出されます.その理由は、2つのchunk(Bufferオブジェクト)の接合が正常ではなく、bufferが行うことに相当するからである.toString() + buffer.toString().bufferが完全でない場合、toStringが出た後のstringには問題があります(例えば、中文字が切断されています).このように出てきたstringはiconvに正常にトランスコードされません.では、正しいつなぎ合わせはどうでしょうか.大神兼好基友@Python発烧友の助けの下で、以下のコードが正しいです.
var chunks = [];
var size = 0;
res.on('data', function (chunk) {
chunks.push(chunk);
size += chunk.length;
});
res.on('end', function () {
var data = null;
switch(chunks.length) {
case 0: data = new Buffer(0);
break;
case 1: data = chunks[0];
break;
default:
data = new Buffer(size);
for (var i = 0, pos = 0, l = chunks.length; i < l; i++) {
var chunk = chunks[i];
chunk.copy(data, pos);
pos += chunk.length;
}
break;
}
});
このときのdataこそ正しいbufferオブジェクトです.
しかし、データを受信するには、このようなシーンは非常に一般的なシーンであるべきで、毎回このようなコードをたくさん書くのは、本当に手間がかかります.では、パッケージを再構築しましょう.
var BufferHelper = function () {
this.buffers = [];
this.size = 0;
this._status = "changed";
};
BufferHelper.prototype.concat = function (buffer) {
for (var i = 0, l = arguments.length; i < l; i++) {
this._concat(arguments[i]);
}
return this;
};
BufferHelper.prototype._concat = function (buffer) {
this.buffers.push(buffer);
this.size = this.size + buffer.length;
this._status = "changed";
return this;
};
BufferHelper.prototype._toBuffer = function () {
var data = null;
var buffers = this.buffers;
switch(buffers.length) {
case 0:
data = new Buffer(0);
break;
case 1:
data = buffers[0];
break;
default:
data = new Buffer(this.size);
for (var i = 0, pos = 0, l = buffers.length; i < l; i++) {
var buffer = buffers[i];
buffer.copy(data, pos);
pos += buffer.length;
}
break;
}
// Cache the computed result
this._status = "computed";
this.buffer = data;
return data;
};
BufferHelper.prototype.toBuffer = function () {
return this._status === "computed" ? this.buffer : this._toBuffer();
};
BufferHelper.prototype.toString = function () {
return Buffer.prototype.toString.apply(this.toBuffer(), arguments);
};
module.exports = BufferHelper;
ここには2つのプライベートメソッドがあります.concatと_toBuffer.その目的は,各メソッドの職責が単一であることを保証し,CPUを無駄にしないようにtoBufferに状態設定を行うことである.次の呼び出しはとても簡単です.
var http = require('http');
var BufferHelper = require('bufferhelper');
http.createServer(function (request, response) {
var bufferHelper = new BufferHelper();
request.on("data", function (chunk) {
bufferHelper.concat(chunk);
});
request.on('end', function () {
var html = bufferHelper.toBuffer().toString();
response.writeHead(200);
response.end(html);
});
}).listen(8001);
コード量がかなり少なく,第1の方法の使用とほぼ同じであることがわかる.うん、さりげなく自慢して、さっぱり:).また、上記のコードは直接requireであることがわかります.
var BufferHelper = require('bufferhelper');
その理由は、npm install bufferhelperで直接できるNPMに公開したからです.プロジェクトアドレスはgithubにあります.https://github.com/JacksonTian/bufferhelper
最後にこのlibはまだユニットテストを書いていないので、圧力測定をして、後で追加します.最后に友达@Pythonの友达に感谢します.最後に、node-iconvの著者はツールセットも提供しています(https://github.com/bnoordhuis/node-buffertools)、一部はc/c++で完成していますが、私のニーズはそんなに複雑ではありません.最も簡単なconcatさえあれば満足できます.このbufferhelperは中国語の環境の下の同級生にとても役に立つと信じています.
ソース:https://cnodejs.org/topic/4faf65852e8fb5bc65113403