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

रॉ डेटा को ट्रांसफ़र करने के लिए, ArrayBuffers का इस्तेमाल किया जाता है. कई नए एपीआई इन पर निर्भर करते हैं. इनमें WebSockets, Web Intents 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 को String में कैसे बदलें. असल में, 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 के ज़रिए टेस्ट किया है और नतीजे से मेरी आशंका की पुष्टि हुई है. डेमो यहां देखें.

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