স্ট্রিমযুক্ত বাফারগুলিকে utf8-স্ট্রিংয়ে রূপান্তর করুন


183

আমি ওয়েবসভার থেকে কিছু পাঠ্য লোড করতে নোড.জেএস ব্যবহার করে এইচটিটিপি-অনুরোধ করতে চাই। যেহেতু প্রতিক্রিয়াতে অনেক পাঠ্য থাকতে পারে (কিছু মেগাবাইট) আমি প্রতিটি পাঠ্যের অংশটি আলাদাভাবে প্রক্রিয়া করতে চাই। আমি নিম্নলিখিত কোড ব্যবহার করে এটি অর্জন করতে পারি:

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') এও করতে পারেন;
— Zugwalt

1
অন্যের উপকারের জন্য আপডেট হিসাবে আপনার উত্তরে উপরের পরামর্শটি যুক্ত করুন। অনেক ধন্যবাদ !
— ফেসপম

9
@ জোশ্প্পেরি: শ্রীল, তবে আমার প্রশ্ন-পাঠ্যটি যেমন ব্যাখ্যা করেছে: chunk.toString('utf8')ইউটিএফ 8-তে বহু-বাইট অক্ষরের কারণে সবসময় কাজ করে না। আপনি কেন আমার উত্তর বদলেছেন তা আমি পাই না যা স্পষ্টভাবে একটি ব্যবহার করে এই সমস্যাটি কাটিয়ে উঠেছে StringDecoder। আমি কি এখানে কিছু মিস করি? হয়েছে nodeকিছু পরিবর্তন হয়েছে?
— বিগী 21

8
আমি বিষয়-শিরোনাম পরিবর্তন করেছি এবং উত্তর সম্পাদনা করেছি। এটি এখন উভয় সমাধান দেখায়: স্ট্রিমযুক্ত বাফার এবং একটি একক বাফার ব্যবহার করে রূপান্তর করে toString।
— বিগী

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);
});
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.