วิธีแปลง ArrayBuffer ไปยังและจากสตริง

ArrayBuffers มีไว้เพื่อส่งข้อมูลดิบและ API ใหม่ๆ จำนวนมากจะอาศัย API ดังกล่าว ซึ่งรวมถึง 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 เป็นอาร์เรย์ไบต์ การแปลงนี้จึงกําหนดให้ปลายทางทั้ง 2 ฝั่งตกลงกันเกี่ยวกับวิธีแสดงอักขระในสตริงเป็นไบต์ คุณอาจเคยเห็น "ข้อตกลง" นี้มาก่อนแล้ว นี่เป็นการเข้ารหัสอักขระของสตริง (และ "เงื่อนไขในข้อตกลง" ตามปกติอย่างเช่น Unicode UTF-16 และ iso8859-1) ดังนั้น สมมติว่าคุณและอีกฝ่ายเห็นพ้องกันในการเข้ารหัส UTF-16 โค้ด Conversion อาจมีลักษณะดังนี้

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 บิต โดยไม่จัดการการเข้ารหัสอักขระด้วยตัวเอง ซึ่งจัดการแบบ Unicode โดย String.fromCharCode และ str.charCodeAt

คำถามเกี่ยวกับ StackOverflow ที่ได้รับความนิยมมีคำตอบที่ได้รับการโหวตสูง ซึ่งมีโซลูชันที่ค่อนข้างซับซ้อนสำหรับ Conversion นั่นคือ สร้าง FileReader เพื่อทำหน้าที่เป็นตัวแปลงและป้อน Blob ที่มีสตริง แม้ว่าวิธีนี้จะได้ผล แต่ก็อ่านไม่ง่ายและฉันคิดว่าช้าไป ในเมื่อความสงสัยที่ไม่มีมูลความจริงก่อให้เกิดความผิดพลาดมากมายในประวัติศาสตร์ของมนุษยชาติ ดังนั้นเราจะใช้วิธีการที่เป็นวิทยาศาสตร์มากขึ้นในที่นี้ ฉันได้ jsperf ทั้ง 2 วิธีแล้ว ซึ่งผลที่ได้ยืนยันความสงสัยของฉัน และคุณดูการสาธิตได้ที่นี่

ใน Chrome 20 การใช้โค้ดการจัดการ ArrayBuffer โดยตรงในบทความนี้จะเร็วกว่าการใช้เมธอด FileReader/Blob ถึงเกือบ 27 เท่า