ArrayBuffer, String'e ve String'den nasıl dönüştürülür

Renato Mangini

ArrayBuffers, ham verileri taşımak için kullanılır ve WebSockets, Web Intents 2](https://www.html5rocks.com/en/tutorials/file/xhr2/) ve WebWorkers gibi çeşitli yeni API'lerden yararlanır. Ancak, JavaScript dünyasına yeni girdikleri için bazen yanlış yorumlanır veya kötüye kullanılır.

Semantik olarak ArrayBuffer, belirli bir maske aracılığıyla görüntülenen bayt dizisidir. ArrayBufferView örneğinin bir örneği olan bu maske, baytların içeriğin beklenen yapısıyla eşleşecek şekilde nasıl hizalanacağını tanımlar. Örneğin, bir ArrayBuffer içindeki baytların 16 bitlik imzalanmamış tam sayılardan oluşan bir diziyi temsil ettiğini biliyorsanız Uint16Array görünümünde ArrayBuffer'ı sarmanız yeterlidir. Bunun yerine, parantez söz dizimini kullanarak Uint16Array öğesini bir tam sayı dizisiymiş gibi kullanabilirsiniz:

// 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 hakkında sık sorulan pratik sorulardan biri, String değerinin ArrayBuffer ve bunun tersinin nasıl dönüştürüleceğidir. ArrayBuffer aslında bir bayt dizisi olduğundan, bu dönüşüm için her iki ucun da Dizedeki karakterlerin bayt olarak nasıl temsil edileceği konusunda hemfikir olması gerekir. Bu "anlaşmayı" daha önce görmüş olabilirsiniz: Bu, Dizenin karakter kodlamasıdır (ve olağan "anlaşma şartları ", örneğin Unicode UTF-16 ve iso8859-1'dir). Diğer tarafın UTF-16 kodlaması üzerinde anlaştığınızı varsayarsak dönüşüm kodu aşağıdaki gibi olabilir:

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 kullanımına dikkat edin. Bu, ArrayBuffers baytlarını 16 bit öğeler olarak hizalayan bir ArrayBuffer görünümüdür. String.fromCharCode ve str.charCodeAt tarafından Unicode olarak işlenen karakter kodlamasını işlemez.

StackOverflow'un bu konuyla ilgili popüler bir sorusunun, dönüşümle ilgili karmaşık bir çözümü olan, çok oy alan bir yanıtı var: Dönüştürücü olarak hareket etmek için bir FileReader oluşturun ve Dizeyi içeren bir Blob feed'i yayınlayın. Bu yöntem işe yarıyor olsa da okunabilirliği düşük ve yavaş olduğundan şüpheleniyorum. İnsanlık tarihindeki pek çok hataya temelsiz şüpheler yol açtığı için burada daha bilimsel bir yaklaşım getirelim. İki yöntemi de jsperf' haline getirdim. Sonuç olarak bu konudaki şüphelerim doğru. Buradan demoya göz atabilirsiniz.

Chrome 20'de, bu makalede doğrudan ArrayBuffer manipülasyon kodu kullanmak, FileReader/Blob yöntemine kıyasla neredeyse 27 kat daha hızlıdır.