Cara mengonversi ArrayBuffer ke dan dari String

Renato Mangini

ArrayBuffer digunakan untuk mengangkut data mentah dan beberapa API baru bergantung padanya, termasuk WebSockets, Web Intents 2](https://www.html5rocks.com/en/tutorials/file/xhr2/) dan WebWorkers. Namun, karena baru-baru ini muncul di dunia JavaScript, terkadang fungsi ini disalahartikan atau disalahgunakan.

Secara semantik, ArrayBuffer hanyalah array byte yang dilihat melalui mask tertentu. Topeng ini, instance ArrayBufferView, menentukan cara byte disejajarkan agar cocok dengan struktur konten yang diharapkan. Misalnya, jika Anda tahu bahwa byte dalam ArrayBuffer mewakili array bilangan bulat tanpa tanda tangan 16-bit, Anda cukup menggabungkan ArrayBuffer dalam tampilan Uint16Array dan Anda dapat memanipulasi elemennya menggunakan sintaksis tanda kurung seolah-olah Uint16Array adalah array bilangan bulat:

// 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]

Salah satu pertanyaan praktis umum tentang ArrayBuffer adalah cara mengonversi String menjadi ArrayBuffer dan sebaliknya. Karena ArrayBuffer sebenarnya adalah array byte, konversi ini mengharuskan kedua ujung menyepakati cara merepresentasikan karakter dalam String sebagai byte. Anda mungkin pernah melihat "perjanjian" ini sebelumnya: ini adalah encoding karakter String (dan "persyaratan perjanjian" yang biasa, misalnya, Unicode UTF-16 dan iso8859-1). Jadi, jika Anda dan pihak lain telah menyetujui encoding UTF-16, kode konversi dapat berupa:

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;
}

Perhatikan penggunaan Uint16Array. Ini adalah tampilan ArrayBuffer yang meratakan byte ArrayBuffer sebagai elemen 16-bit. Fungsi ini tidak menangani encoding karakter itu sendiri, yang ditangani sebagai Unicode oleh String.fromCharCode dan str.charCodeAt.

Pertanyaan tentang hal ini di StackOverflow yang populer memiliki jawaban dengan jumlah suara terbanyak dengan solusi yang agak rumit untuk konversi: buat FileReader untuk bertindak sebagai pengonversi dan masukkan Blob yang berisi String ke dalamnya. Meskipun metode ini berfungsi, keterbacaannya buruk dan saya menduga metode ini lambat. Karena kecurigaan yang tidak berdasar telah menyebabkan banyak kesalahan dalam sejarah umat manusia, mari kita gunakan pendekatan yang lebih ilmiah di sini. Saya telah menggunakan jsperf untuk kedua metode tersebut dan hasilnya mengonfirmasi kecurigaan saya dan Anda dapat melihat demo-nya di sini.

Di Chrome 20, penggunaan kode manipulasi ArrayBuffer langsung pada artikel ini hampir 27 kali lebih cepat daripada menggunakan metode FileReader/Blob.