Cara mengonversi ArrayBuffer ke dan dari String

Renato Mangini

ArrayBuffer digunakan untuk memindahkan data mentah dan beberapa API baru bergantung pada API tersebut, termasuk WebSockets, Intent Web 2](https://www.html5Rock.com/en/tutorials/file/xhr2/) dan WebWorkers. Namun, karena baru-baru ini login di dunia JavaScript, terkadang mereka disalahartikan atau disalahgunakan.

Secara semantik, ArrayBuffer hanyalah array byte yang dilihat melalui mask tertentu. Mask ini, instance ArrayBufferView, menentukan cara byte diselaraskan agar cocok dengan struktur konten yang diharapkan. Misalnya, jika Anda tahu bahwa byte dalam ArrayBuffer mewakili array bilangan bulat tanpa tanda tangan 16-bit, cukup gabungkan 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]

Satu pertanyaan praktis umum tentang ArrayBuffer adalah cara mengonversi String menjadi ArrayBuffer, dan sebaliknya. Karena sebenarnya ArrayBuffer adalah array byte, konversi ini mengharuskan kedua ujung untuk menyepakati cara merepresentasikan karakter dalam String sebagai byte. Anda mungkin sudah pernah melihat "perjanjian" ini sebelumnya: ini adalah encoding karakter String (dan "persyaratan perjanjian" yang biasa digunakan, misalnya, Unicode UTF-16 dan iso8859-1). Jadi, dengan asumsi Anda dan pihak lainnya telah menyetujui encoding UTF-16, kode konversinya dapat menjadi seperti ini:

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 menyelaraskan byte ArrayBuffer sebagai elemen 16-bit. Modul ini tidak menangani encoding karakternya sendiri, yang ditangani sebagai Unicode oleh String.fromCharCode dan str.charCodeAt.

Pertanyaan yang populer tentang StackOverflow tentang hal ini memiliki jawaban yang banyak dipilih dengan solusi yang agak berbelit-belit untuk konversi: buat FileReader untuk bertindak sebagai pengonversi dan masukkan Blob yang berisi String ke dalamnya. Meskipun berhasil, metode ini memiliki keterbacaan yang buruk dan saya menduga metode ini lambat. Karena kecurigaan yang tidak berdasar telah mendorong banyak kesalahan dalam sejarah umat manusia, mari kita gunakan pendekatan yang lebih ilmiah di sini. Saya telah jsperf memeriksa kedua metode tersebut dan hasilnya mengonfirmasi kecurigaan saya, lalu Anda melihat demonya di sini.

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