نحوه تبدیل ArrayBuffer به و از رشته

ArrayBuffer ها برای انتقال داده های خام استفاده می شوند و چندین API جدید از جمله WebSockets ، Web Intents 2](https://www.html5rocks.com/en/tutorials/file/xhr2/) و WebWorkers به ​​آن ها متکی هستند. با این حال، از آنجایی که آنها اخیراً در دنیای جاوا اسکریپت قرار گرفته اند، گاهی اوقات از آنها سوء تعبیر یا سوء استفاده می شود.

از نظر معنایی، یک 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 است (و "شرایط توافق" معمول، برای مثال، Unicode 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 است که بایت های ArrayBuffer ها را به عنوان عناصر 16 بیتی تراز می کند. خود رمزگذاری کاراکتر را که توسط String.fromCharCode و str.charCodeAt به عنوان Unicode مدیریت می شود، کنترل نمی کند.

یک سوال محبوب StackOverflow در مورد این، یک پاسخ بسیار موافق با یک راه حل تا حدی پیچیده برای تبدیل دارد: یک FileReader ایجاد کنید تا به عنوان مبدل عمل کند و یک Blob حاوی رشته را به آن وارد کنید. اگرچه این روش کار می کند، اما خوانایی ضعیفی دارد و به نظر من کند است. از آنجایی که سوء ظن های بی اساس باعث اشتباهات بسیاری در تاریخ بشریت شده است، بیایید در اینجا رویکرد علمی تری داشته باشیم. من دو روش را jsperf'ed کرده ام و نتیجه شک من را تأیید می کند و شما نسخه آزمایشی را در اینجا بررسی کنید .

در کروم 20، استفاده از کد دستکاری مستقیم ArrayBuffer در این مقاله تقریباً 27 برابر سریعتر از استفاده از روش FileReader / Blob است.