परिवर्तित बफ़र्स को utf8-string में बदलें


183

मैं एक वेबसर्वर से कुछ पाठ लोड करने के लिए नोड.जेएस का उपयोग करके HTTP-request करना चाहता हूं। चूंकि प्रतिक्रिया में बहुत अधिक पाठ (कुछ मेगाबाइट) हो सकते हैं इसलिए मैं प्रत्येक पाठ को अलग से संसाधित करना चाहता हूं। मैं निम्नलिखित कोड का उपयोग करके इसे प्राप्त कर सकता हूं:

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'कि दो बाइट्स होते हैं: 0xC3और 0x84। यदि पहली बाइट को पहले चंक ( Buffer) और दूसरी बाइट को दूसरे चंक द्वारा कवर किया जाता है, तो chunk.toString('utf8')टेक्स्ट चंक के अंत / शुरुआत में गलत वर्ण उत्पन्न करेगा। इससे कैसे बचा जा सकता है?

संकेत: मुझे अभी भी बफर की आवश्यकता है (अधिक विशेष रूप से बफर में बाइट्स की संख्या) डाउनलोड बाइट्स की संख्या को सीमित करने के लिए। इसलिए res.setEncoding('utf8')गैर-संपीड़ित डेटा के लिए ऊपर दिए गए पहले उदाहरण कोड का उपयोग करना मेरी आवश्यकताओं के अनुरूप नहीं है।

जवाबों:


289

एकल बफ़र

यदि आपके पास एक एकल है 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-चैकर का पहला बाइट पहले Buffer(चंक) में और दूसरा बाइट में समाहित हो सकता है, Bufferतो आपको ए का उपयोग करना चाहिए StringDecoder। :

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तब तक बफ़र किए जाते हैं जब तक कि सभी आवश्यक बाइट्स डिकोडर को नहीं लिखे जाते।


63
तुम भी chunk.toString ('utf8') कर सकते हैं;
जुगवाल्ट

1
कृपया अपने उत्तर में उपरोक्त सुझाव को दूसरों के लाभ के लिए अद्यतन के रूप में जोड़ें। बहुत धन्यवाद !
फेसप्लम

9
@joshperry: sry, लेकिन जैसा कि मेरा प्रश्न-पाठ बताता है: chunk.toString('utf8')हमेशा यूटीएफ 8 में मल्टी-बाइट पात्रों के कारण काम नहीं करता है। मुझे नहीं पता कि आपने अपना उत्तर क्यों बदल दिया, जो स्पष्ट रूप से इस समस्या को दूर करता है StringDecoder। क्या मुझे यहाँ कुछ याद आता है? गया है nodeकुछ बदल गया?
बिग जी

8
मैंने विषय-शीर्षक बदल दिया और उत्तर को संपादित कर दिया। अब यह दोनों समाधान दिखाता है: स्ट्रीम किए गए बफ़र्स और एकल बफर का उपयोग करके परिवर्तित करना toString
Biggie

1
यह दिखाने के लिए धन्यवाद कि किस तरह से उस स्थिति से ठीक से निपटना है जहां बहु-बाइट वर्ण विखंडू में विभाजित हैं। इंटरनेट पर कई अन्य संसाधन इसे पूरी तरह से नजरअंदाज कर देते हैं, जो छोटी गाड़ी कोड की ओर जाता है जो अक्सर तब तक विफल नहीं होगा जब तक कि यह उत्पादन में न हो।
jlh

-4
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);
});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.