TypeScript'te ArrayBuffer
Bu makale, TypeScript'te ArrayBuffer'ı açıklar.
ArrayBuffer'ı TypeScript'te adım adım, temellerden pratik tekniklere kadar açıklayacağız.
YouTube Video
TypeScript'te ArrayBuffer
ArrayBuffer, ikili veriler için "ham bellek alanını" temsil eden yerleşik bir nesnedir. Sabit uzunlukta ham bir tamponu temsil eder ve bunun üzerine okuma ve yazma için TypedArray veya DataView yerleştirilir.
ArrayBuffer'ın Temel Kavramları ve Özellikleri
ArrayBuffer, sabit uzunlukta bir bayt dizisidir. Oluştururken boyutu bayt cinsinden belirtirsiniz ve uzunluğu daha sonradan değiştirilemez.
1// Create a new ArrayBuffer of 16 bytes.
2const buf = new ArrayBuffer(16);
3console.log(buf.byteLength); // 16
- Bu kod, 16 bayttan oluşan boş bir tampon oluşturur. Boyutu
byteLengthile kontrol edebilirsiniz.
TypedArray ve DataView — Arabellekleri Manipüle Etmek için Görünümler
ArrayBuffer veri okuma veya yazma yeteneğine sahip değildir. Bu nedenle, gerçek işlemler TypedArray veya DataView aracılığıyla gerçekleştirilir; verilere erişirken tamsayı veya kayan noktalı sayı gibi veri türleri ve bayt sırası (endianness) belirtilir.
1// Create a buffer and a Uint8Array view over it. Then write bytes and read them.
2const buffer = new ArrayBuffer(8);
3const u8 = new Uint8Array(buffer);
4
5u8[0] = 0x41; // 'A'
6u8[1] = 0x42; // 'B'
7console.log(u8); // Uint8Array(8) [ 65, 66, 0, 0, 0, 0, 0, 0 ]
Uint8Arraybayt bazında bir dizi görünümüdür ve normal bir dizi gibi erişebilirsiniz. AynıArrayBufferüzerinde birden fazla görünüm yerleştirirseniz, okuma ve yazma açısından aynı belleği paylaşırlar.
DataView: Keyfi Sınır ve Endianness’te Okuma ve Yazma
DataView, bayt bazında ince ayarlı okuma ve yazma için kullanışlıdır ve küçük veya büyük endian belirlemenize olanak tanır.
1// Using DataView to write/read multi-byte values with endianness control.
2const buf2 = new ArrayBuffer(8);
3const view = new DataView(buf2);
4
5// Write a 32-bit integer (little-endian)
6view.setInt32(0, 0x12345678, true);
7
8// Read it back as little-endian and big-endian
9const little = view.getInt32(0, true);
10const big = view.getInt32(0, false);
11console.log(little.toString(16)); // "12345678"
12console.log(big.toString(16)); // "78563412"
DataView, bellek içindeki offsetleri belirterek değer okuma ve yazma olanağı sağlar; bu da ağ bayt sırasını yönetmesi gereken protokollerin uygulanması için uygundur.
Metinler İle ArrayBuffer Arasında Dönüştürme (TextEncoder / TextDecoder)
Metni ikili biçime ve tersine dönüştürmek için TextEncoder ve TextDecoder kullanın.
1// Convert string -> ArrayBuffer and back using TextEncoder/TextDecoder.
2const encoder = new TextEncoder();
3const decoder = new TextDecoder();
4
5// Unicode escape sequences
6const str = "\u3053\u3093\u306B\u3061\u306F";
7const encoded = encoder.encode(str); // Uint8Array
8console.log(encoded); // Uint8Array([...])
9
10// If you need an ArrayBuffer specifically:
11const ab = encoded.buffer.slice(encoded.byteOffset, encoded.byteOffset + encoded.byteLength);
12console.log(ab.byteLength); // bytes length of encoded text
13
14// Decode back
15const decoded = decoder.decode(encoded);
16console.log(decoded);TextEncoder.encode, birUint8Arraydöndürür; birArrayBuffer'a ihtiyaç duyarsanız,.bufferözelliğine başvurmalısınız.sliceyöntemiyle, offset ve uzunluk belirterek gerekli veriyi çıkarabilirsiniz.
ArrayBuffer'ı Dilimleme ve Kopyalama
slice yöntemi yeni bir ArrayBuffer döndürür. ArrayBuffer yeniden boyutlandırılamaz; eğer boyutlandırma gerekliyse, yeni bir arabellek oluşturun ve veriyi ona kopyalayın.
1// Slice an ArrayBuffer and copy to a new sized buffer.
2const original = new Uint8Array([1,2,3,4,5]).buffer;
3const part = original.slice(1, 4); // bytes 1..3
4console.log(new Uint8Array(part)); // Uint8Array [ 2, 3, 4 ]
5
6// Resize: create a new buffer and copy existing content
7const larger = new ArrayBuffer(10);
8const target = new Uint8Array(larger);
9target.set(new Uint8Array(original), 0);
10console.log(target); // first bytes filled with original data
sliceyöntemi yeni birArrayBufferdöndürdüğü için, eğer verimliliği ya da referans paylaşımını önceliklendiriyorsanız, aynı arabelleğe başvurmak içinTypedArray’insubarrayyöntemini kullanabilirsiniz.
TypedArray.subarray ile Kopyalama Arasındaki Fark
TypedArray'nin subarray'i, aynı ArrayBuffer'a atıfta bulunan yeni bir görünüm döndürür.
1// subarray shares the same underlying buffer; modifying one affects the other.
2const arr = new Uint8Array([10,20,30,40]);
3const viewSub = arr.subarray(1,3); // shares memory
4viewSub[0] = 99;
5console.log(arr); // Uint8Array [10, 99, 30, 40]
- Paylaşılan görünümler kopyalama maliyetinden kaçınabilir, fakat aynı arabelleğe başvurduklarından yan etkiler konusunda dikkatli olmalısınız.
Tamponları Birleştirme (Birden Çok ArrayBuffer'ı Birleştirme)
ArrayBuffer sabit uzunlukta olduğundan, birden fazla tamponu birleştirmek için yeni bir ArrayBuffer oluşturup verileri kopyalayın.
1// Concatenate multiple ArrayBuffers
2function concatBuffers(buffers: ArrayBuffer[]): ArrayBuffer {
3 const total = buffers.reduce((sum, b) => sum + b.byteLength, 0);
4 const result = new Uint8Array(total);
5 let offset = 0;
6 for (const b of buffers) {
7 const u8 = new Uint8Array(b);
8 result.set(u8, offset);
9 offset += u8.length;
10 }
11 return result.buffer;
12}
13
14const a = new Uint8Array([1,2]).buffer;
15const b = new Uint8Array([3,4,5]).buffer;
16const c = concatBuffers([a, b]);
17console.log(new Uint8Array(c)); // [1,2,3,4,5]
- Eğer sık sık büyük miktarda veri birleştiriyorsanız, bu koddaki gibi toplam boyutu önceden hesaplayıp yeni bir arabelleği yalnızca bir kez ayırmak daha verimlidir.
Bir Worker'a ArrayBuffer Aktarma (Transfer Edilebilir)
Tarayıcıda postMessage ile bir ArrayBuffer'ı "transferable" (aktarılabilir) bir nesne olarak aktarabilirsiniz. Sahiplik kopyalama olmadan aktarılabilir; bu da kopyalama maliyetinden kaçınmayı sağlar.
1// Example: posting an ArrayBuffer to a Worker as a transferable object (browser)
2const worker = new Worker('worker.js');
3const bufferToSend = new Uint8Array([1,2,3,4]).buffer;
4
5// Transfer ownership to the worker (main thread no longer owns it)
6worker.postMessage(bufferToSend, [bufferToSend]);
7
8// After transfer, bufferToSend.byteLength === 0 in many browsers (detached)
9console.log(bufferToSend.byteLength); // may be 0
postMessage’in ikinci argümanı olarak aktarılacak nesneleri bir dizi içinde belirterek,ArrayBuffergibi aktarılabilir nesnelerin sahipliğini kopyalamadan transfer edebilirsiniz.- Aktarımdan sonra arabellek, orijinal tarafta "detached" (ayrılmış) hale gelir ve artık erişilemez.
SharedArrayBufferkullanmak birden fazla iş parçacığından eşzamanlı erişime izin verir, ancak kullanımı güvenlik gereksinimleri ve ortam sınırlamalarıyla birlikte gelir.
Node.js'de Kullanım (Buffer ile Karşılıklı Dönüştürme)
Node.js'de, Node.js'in ikili türü olan Buffer ile ArrayBuffer arasında dönüştürme yapabilirsiniz. TypeScript ile hem tarayıcıları hem de Node.js'i hedeflerken bu oldukça kullanışlıdır.
1// Convert ArrayBuffer <-> Node.js Buffer
2// In Node.js environment:
3const ab = new Uint8Array([10,20,30]).buffer;
4const nodeBuffer = Buffer.from(ab); // ArrayBuffer -> Buffer
5console.log(nodeBuffer); // <Buffer 0a 14 1e>
6
7const backToAb = nodeBuffer.buffer.slice(
8 nodeBuffer.byteOffset,
9 nodeBuffer.byteOffset + nodeBuffer.byteLength
10);
11console.log(new Uint8Array(backToAb)); // Uint8Array [10,20,30]
- Node.js'de
Buffer.from(arrayBuffer)genellikle bir kopya oluşturur, ancak referans paylaşımının mümkün olduğu durumlar da vardır, bu nedenle offsetlere dikkat edilmelidir.
Performans Dikkatleri ve En İyi Uygulamalar
Performansı optimize etmek ve ArrayBuffer'ı verimli şekilde kullanmak için dikkate alınması gereken birkaç önemli nokta vardır. Aşağıda, pratik en iyi uygulamaları listeliyor ve açıklıyoruz.
-
Kopya Sayısını Azaltın Büyük ikili verilerle çalışırken, kopyaları azaltmak için
subarray(paylaşılan görünüm) veya transfer edilebilirleri kullanın. -
Büyük Tamponları Bir Defada Ayırın Küçük tamponların tekrar tekrar tahsis edilmesi genel yükü artırır. Mümkünse, büyük bir tamponu bir seferde tahsis edin ve gerektiğinde bölümlerini kullanın.
-
Endianness'i Açıkça Belirtin Çok baytlı değerlerle çalışırken,
DataViewkullanın ve endianness'i açıkça belirtin. Büyük endian genellikle ağ protokolleri için standarttır.
Yaygın Kullanım Örneği Senaryoları
ArrayBuffer, hem tarayıcılarda hem de Node.js'de yaygın olarak kullanılır.
- İkili protokolleri ayrıştırma ve oluşturma (
DataViewile başlık bilgisini işleme) - Görüntü ve ses verisi gibi medya işlemleri (
fetch(...).then(res => res.arrayBuffer())) - WebAssembly için paylaşılan bellek (Wasm belleği
ArrayBuffertemellidir) - Ağır işlemleri Worker'lara aktarma (
ArrayBuffer'ı transferable olarak aktarma)
Aşağıdaki kod, ikili veri elde etme ve analiz etme örneğidir.
1// Example: fetch binary data in browser and inspect first bytes
2async function fetchAndInspect(url: string) {
3 const resp = await fetch(url);
4 const ab = await resp.arrayBuffer();
5 const u8 = new Uint8Array(ab, 0, Math.min(16, ab.byteLength));
6 console.log('first bytes:', u8);
7}- Bu kod, tarayıcıda herhangi bir URL'den ikili veri alır ve ilk birkaç baytı gösterir. Kod,
fetchAPI'siyle alınan veriyiArrayBufferolarak yükler ve ilk 16 baytıUint8Arrayile inceler.
Özet
ArrayBuffer, ham bir bellek temsili olup, TypedArray ve DataView ile verimli ikili işlemleri mümkün kılar. Gereksiz kopyalamalardan kaçınacak ve endianness’i açıkça belirtecek şekilde tasarım yaparak, güvenli ve yüksek performanslı ikili veri işleme elde edebilirsiniz.
Yukarıdaki makaleyi, YouTube kanalımızda Visual Studio Code'u kullanarak takip edebilirsiniz. Lütfen YouTube kanalını da kontrol edin.