197

node.jsを使用してHTTPリクエストを作成し、ウェブサーバーからテキストをロードしたいと思います。応答には多くのテキスト(数メガバイト)が含まれる可能性があるため、各テキストチャンクを個別に処理したいと思います。次のコードを使用してこれを実現できます。

var req = http.request(reqOptions, function(res) {
    ...
    res.setEncoding('utf8');
    res.on('data', function(textChunk) {
        // process utf8 text chunk
    });
});

これは問題なく機能するようです。ただし、HTTP圧縮をサポートしたいので、zlibを使用します。

var zip = zlib.createUnzip();

// NO res.setEncoding('utf8') here since we need the raw bytes for zlib
res.on('data', function(chunk) {
    // do something like checking the number of bytes downloaded
    zip.write(chunk); // give the raw bytes to zlib, s.b.
});

zip.on('data', function(chunk) {
    // convert chunk to utf8 text:
    var textChunk = chunk.toString('utf8');

    // process utf8 text chunk
});

'\u00c4'これは、次の2バイトで構成されるマルチバイト文字の場合に問題になる可能性が0xC3あり0x84ます。最初のバイトが最初のチャンク(Buffer)で覆われ、2番目のバイトが2番目のチャンクで覆われている場合chunk.toString('utf8')、テキストチャンクの終わり/始まりで誤った文字が生成されます。どうすればこれを回避できますか?

ヒント:ダウンロードされるバイト数を制限するには、まだバッファー(より具体的にはバッファー内のバイト数)が必要です。したがってres.setEncoding('utf8')、上記の最初のサンプルコードのように非圧縮データに使用することは、私のニーズには合いません。

4

2 に答える 2

312

シングルバッファ

シングルがある場合は、特定のエンコーディングを使用してバイナリコンテンツのすべてまたは一部を文字列に変換するメソッドをBuffer使用できます。パラメータを指定しない場合、toStringデフォルトでデフォルトになりますが、この例ではエンコーディングを明示的に設定しました。utf8

var req = http.request(reqOptions, function(res) {
    ...

    res.on('data', function(chunk) {
        var textChunk = chunk.toString('utf8');
        // process utf8 text chunk
    });
});

ストリーミングバッファ

上記の質問のように、マルチバイト文字の最初のバイトが最初の(チャンク)UTF8に含まれ、 2番目のバイトが2番目のバイトに含まれる可能性があるバッファをストリーミングした場合は、を使用する必要があります。:BufferBufferStringDecoder

var StringDecoder = require('string_decoder').StringDecoder;

var req = http.request(reqOptions, function(res) {
    ...
    var decoder = new StringDecoder('utf8');

    res.on('data', function(chunk) {
        var textChunk = decoder.write(chunk);
        // process utf8 text chunk
    });
});

このようにして、不完全なStringDecoder文字のバイトは、必要なすべてのバイトがデコーダーに書き込まれるまでバッファリングされます。

于 2012-08-25T14:05:28.917 に答える
-5
var fs = require("fs");

function readFileLineByLine(filename, processline) {
    var stream = fs.createReadStream(filename);
    var s = "";
    stream.on("data", function(data) {
        s += data.toString('utf8');
        var lines = s.split("\n");
        for (var i = 0; i < lines.length - 1; i++)
            processline(lines[i]);
        s = lines[lines.length - 1];
    });

    stream.on("end",function() {
        var lines = s.split("\n");
        for (var i = 0; i < lines.length; i++)
            processline(lines[i]);
    });
}

var linenumber = 0;
readFileLineByLine(filename, function(line) {
    console.log(++linenumber + " -- " + line);
});
于 2016-10-02T12:02:07.663 に答える