नोड में बाइनरी डेटा को बफ़र में कैसे जोड़ें


84

मेरे पास कुछ बाइनरी डेटा के साथ एक बफर है:

var b = new Buffer ([0x00, 0x01, 0x02]);

और मैं जोड़ना चाहता हूं 0x03

मैं अधिक बाइनरी डेटा कैसे जोड़ सकता हूं? मैं दस्तावेज़ीकरण में खोज कर रहा हूं, लेकिन डेटा को जोड़ने के लिए यह एक स्ट्रिंग होना चाहिए, यदि नहीं, तो एक त्रुटि होती है ( TypeError: Argument स्ट्रिंग होना चाहिए ):

var b = new Buffer (256);
b.write ("hola");
console.log (b.toString ("utf8", 0, 4)); //hola
b.write (", adios", 4);
console.log (b.toString ("utf8", 0, 11)); //hola, adios

फिर, एकमात्र समाधान जो मैं यहां देख सकता हूं, वह है कि प्रत्येक संलग्न बाइनरी डेटा के लिए एक नया बफर बनाना और इसे सही बफर के साथ प्रमुख बफर में कॉपी करना है:

var b = new Buffer (4); //4 for having a nice printed buffer, but the size will be 16KB
new Buffer ([0x00, 0x01, 0x02]).copy (b);
console.log (b); //<Buffer 00 01 02 00>
new Buffer ([0x03]).copy (b, 3);
console.log (b); //<Buffer 00 01 02 03>

लेकिन यह थोड़ा अक्षम लगता है क्योंकि मुझे हर ऐपेंड के लिए एक नया बफर इंस्टेंट करना होगा।

क्या आप द्विआधारी डेटा को जोड़ने के लिए एक बेहतर तरीका जानते हैं?

संपादित करें

मैंने एक बफ़रड्राइवर लिखा है जो आंतरिक बफ़र्स का उपयोग करके किसी फ़ाइल को बाइट्स लिखता है। के रूप में ही BufferedReader लेकिन लिखने के लिए।

एक त्वरित उदाहरण:

//The BufferedWriter truncates the file because append == false
new BufferedWriter ("file")
    .on ("error", function (error){
        console.log (error);
    })

    //From the beginning of the file:
    .write ([0x00, 0x01, 0x02], 0, 3) //Writes 0x00, 0x01, 0x02
    .write (new Buffer ([0x03, 0x04]), 1, 1) //Writes 0x04
    .write (0x05) //Writes 0x05
    .close (); //Closes the writer. A flush is implicitly done.

//The BufferedWriter appends content to the end of the file because append == true
new BufferedWriter ("file", true)
    .on ("error", function (error){
        console.log (error);
    })

    //From the end of the file:
    .write (0xFF) //Writes 0xFF
    .close (); //Closes the writer. A flush is implicitly done.

//The file contains: 0x00, 0x01, 0x02, 0x04, 0x05, 0xFF

आखिरी अपडेट

कॉन्सेट का इस्तेमाल करें ।


3
यह पढ़ने के लिए स्पष्ट होगा कि क्या शीर्ष पर मिनी-उत्तर वास्तविक उत्तर थे और सवाल यहाँ अपने आप था।
एको

जवाबों:


140

Node.js के लिए अद्यतित उत्तर ~> 0.8

नोड अपने आप अब बफ़र्स को समाप्‍त करने में सक्षम है ।

var newBuffer = Buffer.concat([buffer1, buffer2]);

Node.js ~ 0.6 के लिए पुराना उत्तर

मैं .concatदूसरों के बीच एक फंक्शन जोड़ने के लिए मॉड्यूल का उपयोग करता हूं :

https://github.com/coolaj86/node-bufferjs

मुझे पता है कि यह "शुद्ध" समाधान नहीं है, लेकिन यह मेरे उद्देश्यों के लिए बहुत अच्छा काम करता है।


concatसमारोह वास्तव में क्या करता है मैं पोस्ट किया है :( यह गणना डे कुल लंबाई और फिर प्रतियां का समायोजन सभी बफ़र्स का डेटा ऑफसेट।।
गेब्रियल Llamas

इसी तरह काम करना है। जैसा कि @stewe ने बताया, बफ़र्स को निश्चित आकार में लाया जाता है, जिस तरह से मेमोरी आवंटित की जाती है।
ब्रैड

2
लेकिन ग में हमारे पास आवश्यक रूप से मेमोरी को गतिशील रूप से विस्तारित करने के लिए रियलोकॉक फ़ंक्शन है। नोड.जेएस को यह जानना चाहिए।
गेब्रियल ललमास

1
@ गैब्रिएललामास, मैं उनके रिपॉजिटरी को एक पैच सबमिट करने की सलाह दूंगा।
ब्रैड

11
मैंने पाया है कि नोड.जेएस के पास गतिशील बफ़र्स क्यों नहीं हैं: markmail.org/message/vx2h3uslwgludu3y
गेब्रियल

10

बफ़र हमेशा निश्चित आकार के होते हैं, उन्हें गतिशील रूप से आकार देने के लिए कोई तरीका नहीं बनाया जाता है, इसलिए इसे बड़े बफ़र पर कॉपी करने का आपका तरीका एकमात्र तरीका है।

हालांकि, अधिक कुशल होने के लिए, आप बफ़र को मूल सामग्रियों से बड़ा बना सकते हैं, इसलिए इसमें कुछ "मुक्त" स्थान होते हैं जहाँ आप बफ़र को पुनः लोड किए बिना डेटा जोड़ सकते हैं। इस तरह आपको एक नया बफ़र बनाने और प्रत्येक परिशिष्ट पर सामग्री को कॉपी करने की आवश्यकता नहीं है।


8

यह किसी ऐसे व्यक्ति की मदद करना है जो यहां एक समाधान की तलाश में आता है जो शुद्ध दृष्टिकोण चाहता है। मैं इस समस्या को समझने की सलाह दूंगा क्योंकि यह बहुत सी अलग-अलग जगहों पर हो सकता है न कि सिर्फ जेएस बफर ऑब्जेक्ट के साथ। यह समझने से कि समस्या मौजूद क्यों है और इसे कैसे हल किया जाए आप भविष्य में अन्य समस्याओं को हल करने की अपनी क्षमता में सुधार करेंगे क्योंकि यह बहुत मौलिक है।

हममें से जिन लोगों को अन्य भाषाओं में इन समस्याओं से जूझना पड़ता है, उनके लिए समाधान तैयार करना काफी स्वाभाविक है, लेकिन ऐसे लोग भी हैं जो महसूस नहीं कर सकते कि कैसे जटिलताओं को दूर किया जाए और आम तौर पर कुशल गतिशील बफर को लागू किया जाए। नीचे दिए गए कोड में आगे अनुकूलित किए जाने की क्षमता हो सकती है।

मैंने उदाहरण के आकार में छोटा रखने के लिए पढ़ी गई विधि को छोड़ दिया है।

reallocसी में समारोह (या आंतरिक आवंटन के साथ किसी भी भाषा निपटने) गारंटी नहीं है कि आवंटन मौजूदा डेटा ले जाने के बाहर के साथ आकार में विस्तार किया जाएगा - हालांकि कभी-कभी यह संभव है। इसलिए अधिकांश एप्लिकेशन जब डेटा की अज्ञात मात्रा को स्टोर करने की आवश्यकता होती है, तो नीचे की तरह एक विधि का उपयोग करेगी और लगातार रीकॉलोकैट नहीं करेगी, जब तक कि रीकॉलोकेशन बहुत अधिक न हो। यह अनिवार्य रूप से है कि अधिकांश फ़ाइल सिस्टम किसी फ़ाइल को डेटा लिखने से कैसे निपटते हैं। फ़ाइल सिस्टम बस एक और नोड आवंटित करता है और सभी नोड्स को एक साथ जोड़ा जाता है, और जब आप इसे पढ़ते हैं तो जटिलता दूर हो जाती है ताकि फ़ाइल / बफर एक एकल सन्निहित बफर प्रतीत हो।

आप में से जो केवल एक उच्च प्रदर्शन गतिशील बफर प्रदान करने में कठिनाई को समझने की इच्छा रखते हैं, उनके लिए आपको केवल नीचे दिए गए कोड को देखने की आवश्यकता है, और मेमोरी हीप एल्गोरिदम और मेमोरी हीप कार्यक्रमों के लिए कैसे काम करता है, इस पर कुछ शोध करें।

अधिकांश भाषाएं प्रदर्शन कारणों से एक निश्चित आकार का बफर प्रदान करेंगी, और फिर एक और संस्करण प्रदान करें जो आकार में गतिशील हो। कुछ भाषा प्रणालियाँ एक तृतीय-पक्ष प्रणाली का विकल्प चुनती हैं जहाँ वे मुख्य कार्यक्षमता को न्यूनतम (कोर वितरण) रखते हैं और डेवलपर्स को अतिरिक्त या उच्च स्तर की समस्याओं को हल करने के लिए पुस्तकालय बनाने के लिए प्रोत्साहित करते हैं। यही कारण है कि आप सवाल कर सकते हैं कि कोई भाषा कुछ कार्यक्षमता क्यों नहीं प्रदान करती है। यह छोटी कोर कार्यक्षमता भाषा को बनाए रखने और बढ़ाने में लागत को कम करने की अनुमति देती है, हालांकि आप अपने स्वयं के कार्यान्वयन को लिखने या तीसरे पक्ष के आधार पर समाप्त करते हैं।

var Buffer_A1 = function (chunk_size) {
    this.buffer_list = [];
    this.total_size = 0;
    this.cur_size = 0;
    this.cur_buffer = [];
    this.chunk_size = chunk_size || 4096;

    this.buffer_list.push(new Buffer(this.chunk_size));
};

Buffer_A1.prototype.writeByteArrayLimited = function (data, offset, length) {
    var can_write = length > (this.chunk_size - this.cur_size) ? (this.chunk_size - this.cur_size) : length;

    var lastbuf = this.buffer_list.length - 1;

    for (var x = 0; x < can_write; ++x) {
        this.buffer_list[lastbuf][this.cur_size + x] = data[x + offset];
    }

    this.cur_size += can_write;
    this.total_size += can_write;

    if (this.cur_size == this.chunk_size) {
        this.buffer_list.push(new Buffer(this.chunk_size));
        this.cur_size = 0;
    }

    return can_write;
};

/*
    The `data` parameter can be anything that is array like. It just must
    support indexing and a length and produce an acceptable value to be
    used with Buffer.
*/
Buffer_A1.prototype.writeByteArray = function (data, offset, length) {
    offset = offset == undefined ? 0 : offset;
    length = length == undefined ? data.length : length;

    var rem = length;
    while (rem > 0) {
        rem -= this.writeByteArrayLimited(data, length - rem, rem);
    }
};

Buffer_A1.prototype.readByteArray = function (data, offset, length) {
    /*
        If you really wanted to implement some read functionality
        then you would have to deal with unaligned reads which could
        span two buffers.
    */
};

Buffer_A1.prototype.getSingleBuffer = function () {
    var obuf = new Buffer(this.total_size);
    var cur_off = 0;
    var x;

    for (x = 0; x < this.buffer_list.length - 1; ++x) {
        this.buffer_list[x].copy(obuf, cur_off);
        cur_off += this.buffer_list[x].length;
    }

    this.buffer_list[x].copy(obuf, cur_off, 0, this.cur_size);

    return obuf;
};

मैं इस समाधान का उपयोग करते समय अत्यधिक सावधानी की सलाह दूंगा। यदि आप चाहते हैं कि रिज्यूम करने योग्य बफ़र प्रदर्शन हो, तो इसका उपयोग न करें । हर एक बाइट रिसाइकिलिंग एरे इंकर्स को लिखा जाता है this.buffer_list[lastbuf][this.cur_size + x] = data[x + offset];, जो हर एक बाइट के साथ एक अतिरिक्त हैश-लुकअप, बहुत सारी एक्सट्रा चेक चेक्स और दो SMI पूर्णांक चेक की जरूरत को बताता है। यदि प्रदर्शन वह है जो आप चाहते हैं, तो मैं दृढ़ता से आग्रह करता हूं कि आप इस उत्तर का उपयोग न करें। इसके बजाय, वांछित आकार का एक नया सरणी आवंटित करें और डेटा को नए सरणी में कॉपी करें। यही जावा करता है और यह वास्तव में तेज़ है।
जैक गिफिन

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.