arrayBuffer को स्ट्रिंग में और स्ट्रिंग से बदलने का तरीका

रेनाटो मंगिनी

ArrayBuffers का इस्तेमाल रॉ डेटा को ट्रांसपोर्ट करने के लिए किया जाता है और कई नए एपीआई उन पर निर्भर होते हैं. इनमें WebSockets, वेब इंटेंट 2](https://www.html5rocks.com/en/tutorials/file/xhr2/) और WebWorkers शामिल हैं. हालांकि, इन टूल का इस्तेमाल हाल ही में JavaScript की मदद से किया जा रहा है. इसलिए, कभी-कभी इनका गलत तरीके से मतलब निकाला जाता है या इसका गलत तरीके से इस्तेमाल किया जाता है.

इसका मतलब है कि ArrayBuffer सिर्फ़ उन बाइट की कैटगरी है जिन्हें किसी खास मास्क से देखा जाता है. ArrayBufferView का इंस्टेंस. यह मास्क बताता है कि कॉन्टेंट के स्ट्रक्चर से मैच करने के लिए, बाइट को किस तरह अलाइन किया जाता है. उदाहरण के लिए, अगर आपको पता है कि arrayBuffer में मौजूद बाइट 16-बिट, बिना साइन किए हुए पूर्णांकों की एक अरे को दिखाती हैं, तो आपको सिर्फ़ ArrayBuffer को Uint16Array व्यू में रैप करना होगा. साथ ही, ब्रैकेट सिंटैक्स का इस्तेमाल करके इसके एलिमेंट में बदलाव करना होगा, जैसे कि Uint16Array एक पूर्णांक कलेक्शन था:

// suppose buf contains the bytes [0x02, 0x01, 0x03, 0x07]
// notice the multibyte values respect the hardware endianess, which is little-endian in x86
var bufView = new Uint16Array(buf);
if (bufView[0]===258) {   // 258 === 0x0102
    console.log("ok");
}
bufView[0] = 255;    // buf now contains the bytes [0xFF, 0x00, 0x03, 0x07]
bufView[0] = 0xff05; // buf now contains the bytes [0x05, 0xFF, 0x03, 0x07]
bufView[1] = 0x0210; // buf now contains the bytes [0x05, 0xFF, 0x10, 0x02]

ArrayBuffer के बारे में एक सामान्य व्यावहारिक सवाल यह है कि एक String को ArrayBuffer और उलटा में कैसे बदला जाए. ArrayBuffer असल में एक बाइट कलेक्शन है. इसलिए, इस कन्वर्ज़न के लिए ज़रूरी है कि दोनों के सिर इस बात से सहमत हों कि स्ट्रिंग के वर्णों को बाइट के तौर पर कैसे दिखाया जाए. आपने शायद पहले यह "एग्रीमेंट" देखा होगा: यह स्ट्रिंग की कैरेक्टर एन्कोडिंग होती है (और आम तौर पर "एग्रीमेंट की शर्तें", उदाहरण के लिए, यूनिकोड UTF-16 और ISO8859-1) होती हैं. इसलिए, यह मानते हुए कि आपने और दूसरे पक्ष ने UTF-16 एन्कोडिंग पर सहमति दी है, कन्वर्ज़न कोड कुछ इस तरह हो सकता है:

function ab2str(buf) {
    return String.fromCharCode.apply(null, new Uint16Array(buf));
}
function str2ab(str) {
    var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
    var bufView = new Uint16Array(buf);
    for (var i=0, strLen=str.length; i < strLen; i++) {
    bufView[i] = str.charCodeAt(i);
    }
    return buf;
}

Uint16Array के इस्तेमाल पर ध्यान दें. यह एक arrayBuffer व्यू है, जो ArrayBuffers के बाइट को 16-बिट एलिमेंट के तौर पर अलाइन करता है. यह अपने-आप कैरेक्टर एन्कोडिंग को हैंडल नहीं करती, जिसे String.fromCharCode और str.charCodeAt, यूनिकोड के तौर पर हैंडल करते हैं.

एक लोकप्रिय StackOverflow इस बारे में सवाल इसमें कन्वर्ज़न का कुछ हद तक जटिल समाधान के साथ एक ऐसा जवाब है जिसे सबसे ज़्यादा वोट मिले हैं: कन्वर्टर के रूप में काम करने के लिए FileReader बनाएं और उसमें स्ट्रिंग शामिल करने वाला Blob फ़ीड करें. हालांकि, यह तरीका काम करता है, लेकिन इसकी रीडबिलिटी खराब है और मुझे लगता है कि यह धीमा है. मानवता के इतिहास में, बेबुनियाद संदेह की वजह से कई गलतियां हुई हैं. चलिए, अब इस विषय पर ज़्यादा वैज्ञानिक नज़रिए से बात करते हैं. मैंने jsperf को दो तरीके बताए हैं और नतीजा मेरे शक की पुष्टि करता है. आपने यहां डेमो देखें.

FileReader/Blob वाले तरीके के मुकाबले, Chrome 20 में इस लेख में मौजूद सीधे ArrayBuffer मैनिप्यूलेशन कोड का इस्तेमाल करने में, करीब 27 गुना तेज़ी से मदद मिलती है.