Veb-ishlab chiqishda biz binary ma’lumotlarni asosan fayllar bilan ishlashda uchratamiz (yaratish, yuklash, yuklab olish). Yana bir tipik foydalanish holati rasm qayta ishlash.
Bularning barchasi JavaScript da mumkin va binary operatsiyalar yuqori samarali.
Garchi, biroz chalkashlik bor, chunki ko’plab klasslar mavjud. Bir nechtasini nomlash uchun:
ArrayBuffer,Uint8Array,DataView,Blob,Fileva hokazo.
JavaScript da binary ma’lumotlar boshqa tillarga nisbatan standart bo’lmagan tarzda amalga oshirilgan. Lekin narsalarni tartibga solsak, hamma narsa juda oddiy bo’ladi.
Asosiy binary obyekt ArrayBuffer – belgilangan uzunlikdagi uzluksiz xotira sohasiga havola.
Biz uni shunday yaratamiz:
let buffer = new ArrayBuffer(16); // 16 uzunlikdagi buffer yaratish
alert(buffer.byteLength); // 16
Bu 16 baytlik uzluksiz xotira sohasini ajratadi va uni nollar bilan oldindan to’ldiradi.
ArrayBuffer biror narsaning arrayi emasKeling, mumkin bo’lgan chalkashlik manbasini bartaraf etaylik. ArrayBuffer ning Array bilan hech qanday umumiylik yo’q:
- U belgilangan uzunlikka ega, biz uni oshira yoki kamaytira olmaymiz.
- U xotirada aniq shuncha joy egallaydi.
- Individual baytlarga kirish uchun boshqa “view” obyekti kerak,
buffer[index]emas.
ArrayBuffer xotira sohasi. Unda nima saqlanadi? Uning hech qanday tasavvuri yo’q. Faqat xom baytlar ketma-ketligi.
ArrayBuffer ni boshqarish uchun bizga “view” obyektidan foydalanishimiz kerak.
View obyekt o’zida hech narsani saqlamaydi. Bu ArrayBuffer da saqlangan baytlarning talqinini beradigan "ko’zoynak"dir.
Masalan:
Uint8Array–ArrayBufferdagi har bir baytni 0 dan 255 gacha mumkin bo’lgan qiymatlar bilan alohida raqam sifatida ko’radi (bayt 8-bitli, shuning uchun faqat shuncha saqlashi mumkin). Bunday qiymat “8-bitli belgisiz butun son” deyiladi.Uint16Array– har 2 baytni 0 dan 65535 gacha mumkin bo’lgan qiymatlar bilan butun son sifatida ko’radi. Bu “16-bitli belgisiz butun son” deyiladi.Uint32Array– har 4 baytni 0 dan 4294967295 gacha mumkin bo’lgan qiymatlar bilan butun son sifatida ko’radi. Bu “32-bitli belgisiz butun son” deyiladi.Float64Array– har 8 baytni5.0x10-324dan1.8x10308gacha mumkin bo’lgan qiymatlar bilan suzuvchi nuqta raqami sifatida ko’radi.
Shunday qilib, 16 baytli ArrayBuffer dagi binary ma’lumotlar 16 ta “kichik raqam” yoki 8 ta kattaroq raqam (har biri 2 bayt) yoki 4 ta yanada kattaroq (har biri 4 bayt) yoki yuqori aniqlikdagi 2 ta suzuvchi nuqta qiymati (har biri 8 bayt) sifatida talqin qilinishi mumkin.
ArrayBuffer asosiy obyekt, hamma narsaning ildizi, xom binary ma’lumot.
Lekin agar biz unga yozmoqchi bo’lsak yoki uni takrorlashni istasak, asosan deyarli har qanday operatsiya uchun – biz view dan foydalanishimiz kerak, masalan:
let buffer = new ArrayBuffer(16); // 16 uzunlikdagi buffer yaratish
let view = new Uint32Array(buffer); // buffer ni 32-bitli butun sonlar ketma-ketligi sifatida ko'rish
alert(Uint32Array.BYTES_PER_ELEMENT); // har butun son uchun 4 bayt
alert(view.length); // 4, shuncha butun sonni saqlaydi
alert(view.byteLength); // 16, baytlardagi o'lcham
// keling, qiymat yozaylik
view[0] = 123456;
// qiymatlar bo'ylab takrorlash
for(let num of view) {
alert(num); // 123456, keyin 0, 0, 0 (jami 4 ta qiymat)
}
TypedArray
Bu barcha view larning (Uint8Array, Uint32Array va hokazo) umumiy atamasi TypedArray. Ular bir xil usullar va xossalar to’plamini baham ko’radi.
Esda tuting, TypedArray deb nomlangan konstruktor yo’q, bu shunchaki ArrayBuffer ustidagi view lardan birini ifodalash uchun umumiy “soyabon” atama: Int8Array, Uint8Array va hokazo, to’liq ro’yxat tez orada keladi.
new TypedArray kabi narsani ko’rganingizda, bu new Int8Array, new Uint8Array va hokazolardan birini anglatadi.
Typed arraylar oddiy arraylar kabi ishlaydi: indekslarga ega va takrorlanadi.
Typed array konstruktori (bu Int8Array yoki Float64Array bo’lishidan qat’i nazar, muhim emas) argument turlariga qarab turlicha ishlaydi.
5 ta argument varianti bor:
new TypedArray(buffer, [byteOffset], [length]);
new TypedArray(object);
new TypedArray(typedArray);
new TypedArray(length);
new TypedArray();
-
Agar
ArrayBufferargumenti berilsa, view uning ustida yaratiladi. Biz bu sintaksisni allaqachon ishlatdik.Ixtiyoriy ravishda boshlanish uchun
byteOffset(standart bo’yicha 0) valength(standart bo’yicha buffer oxirigacha) berishimiz mumkin, keyin view faqatbufferning bir qismini qamrab oladi. -
Agar
Arrayyoki biron bir array-ga o’xshash obyekt berilsa, u bir xil uzunlikdagi typed array yaratadi va kontentni nusxalaydi.Biz uni ma’lumotlar bilan oldindan to’ldirish uchun ishlatishimiz mumkin:
let arr = new Uint8Array([0, 1, 2, 3]); alert( arr.length ); // 4, bir xil uzunlikdagi binary array yaratildi alert( arr[1] ); // 1, berilgan qiymatlar bilan 4 bayt (belgisiz 8-bitli butun sonlar) bilan to'ldirildi -
Agar boshqa
TypedArrayberilsa, u bir xil ish qiladi: bir xil uzunlikdagi typed array yaratadi va qiymatlarni nusxalaydi. Kerak bo’lsa, qiymatlar jarayonda yangi turga aylantiriladi.let arr16 = new Uint16Array([1, 1000]); let arr8 = new Uint8Array(arr16); alert( arr8[0] ); // 1 alert( arr8[1] ); // 232, 1000 ni nusxalashga harakat qildi, lekin 1000 ni 8 bitga sig'dira olmadi (quyida tushuntirishlar) -
Raqamli argument
lengthuchun – shuncha elementga ega typed array yaratadi. Uning bayt uzunligilengthni bitta elementdagi baytlar sonigaTypedArray.BYTES_PER_ELEMENTga ko’paytirilganiga teng bo’ladi:let arr = new Uint16Array(4); // 4 ta butun son uchun typed array yaratish alert( Uint16Array.BYTES_PER_ELEMENT ); // har butun son uchun 2 bayt alert( arr.byteLength ); // 8 (baytlardagi o'lcham) -
Argumentlarsiz, nol uzunlikdagi typed array yaratadi.
Biz ArrayBuffer ni eslatmasdan to’g’ridan-to’g’ri TypedArray yaratishimiz mumkin. Lekin view asosiy ArrayBuffer siz mavjud bo’la olmaydi, shuning uchun birinchisidan tashqari (berilgan vaqtda) barcha hollarda avtomatik yaratiladi.
ArrayBuffer ga kirish uchun xossalar mavjud:
arr.buffer–ArrayBufferga ishora qiladi.arr.byteLength–ArrayBufferning uzunligi.
Shunday qilib, biz har doim bir view dan boshqasiga o’tishimiz mumkin:
let arr8 = new Uint8Array([0, 1, 2, 3]);
// bir xil ma'lumotlardagi boshqa view
let arr16 = new Uint16Array(arr8.buffer);
Mana typed arraylar ro’yxati:
Uint8Array,Uint16Array,Uint32Array– 8, 16 va 32 bitli butun sonlar uchun.Uint8ClampedArray– 8-bitli butun sonlar uchun, tayinlashda ularni “siqadi” (quyida qarang).
Int8Array,Int16Array,Int32Array– belgili butun sonlar uchun (salbiy bo’lishi mumkin).Float32Array,Float64Array– 32 va 64 bitli belgili suzuvchi nuqta sonlari uchun.
int8 yoki shunga o’xshash bitta qiymatli turlar yo’qEsda tuting, Int8Array kabi nomlarga qaramay, JavaScript da int yoki int8 kabi bitta qiymatli tur yo’q.
Bu mantiqiy, chunki Int8Array bu individual qiymatlarning arrayi emas, balki ArrayBuffer ustidagi view.
Chegara tashqaridagi xatti-harakat
Agar biz typed array ga chegara tashqaridagi qiymat yozishga harakat qilsak nima bo’ladi? Hech qanday xato bo’lmaydi. Lekin qo’shimcha bitlar kesiladi.
Masalan, Uint8Array ga 256 ni qo’yishga harakat qilaylik. Binary shaklda 256 100000000 (9 bit), lekin Uint8Array har qiymat uchun faqat 8 bit beradi, bu 0 dan 255 gacha bo’lgan diapazonni yaratadi.
Kattaroq sonlar uchun faqat eng o’ngdagi (kamroq muhim) 8 bit saqlanadi va qolgan qism kesiladi:
Shunday qilib, biz nol olamiz.
257 uchun binary shakl 100000001 (9 bit), eng o’ngdagi 8 ta saqlanadi, shuning uchun arrayda 1 ga ega bo’lamiz:
Boshqacha qilib aytganda, 28 ga bo’lingan qoldiq saqlanadi.
Mana demo:
let uint8array = new Uint8Array(16);
let num = 256;
alert(num.toString(2)); // 100000000 (binary ko'rinish)
uint8array[0] = 256;
uint8array[1] = 257;
alert(uint8array[0]); // 0
alert(uint8array[1]); // 1
Uint8ClampedArray bu jihatdan maxsus, uning xatti-harakati boshqacha. U 255 dan katta har qanday raqam uchun 255 ni va har qanday salbiy raqam uchun 0 ni saqlaydi. Bu xatti-harakat rasm qayta ishlash uchun foydali.
TypedArray usullari
TypedArray oddiy Array usullariga ega, e’tiborli istisnolar bilan.
Biz takrorlashimiz, map, slice, find, reduce va hokazolarni qilishimiz mumkin.
Biroq, biz qila olmaydigan bir necha narsa bor:
spliceyo’q – biz qiymatni “o’chira” olmaymiz, chunki typed arraylar buffer ustidagi view lar va bular belgilangan, uzluksiz xotira sohalari. Biz faqat nol belgilashimiz mumkin.concatusuli yo’q.
Ikkita qo’shimcha usul bor:
arr.set(fromArr, [offset])fromArrdan barcha elementlarniarrga nusxalaydi,offsetpozitsiyasidan boshlab (standart bo’yicha 0).arr.subarray([begin, end])begindanendgacha (eksklyuziv) bir xil turdagi yangi view yaratadi. Busliceusuliga o’xshash (bu ham qo’llab-quvvatlanadi), lekin hech narsani nusxalamaydi – faqat berilgan ma’lumot qismi bilan ishlash uchun yangi view yaratadi.
Bu usullar bizga typed arraylarni nusxalash, aralashtirishimiz, mavjudlaridan yangi arraylar yaratishimiz va hokazolarni qilish imkonini beradi.
DataView
DataView ArrayBuffer ustidagi maxsus super-moslashuvchan “tursiz” view. U har qanday offsetda har qanday formatda ma’lumotlarga kirishga imkon beradi.
- Typed arraylar uchun konstruktor format nima ekanligini belgilaydi. Butun array bir xil bo’lishi kerak. i-chi raqam
arr[i]. DataViewbilan biz.getUint8(i)yoki.getUint16(i)kabi usullar bilan ma’lumotlarga kiramiz. Biz konstruksiya vaqti o’rniga usul chaqirish vaqtida formatni tanlaymiz.
Sintaksis:
new DataView(buffer, [byteOffset], [byteLength])
buffer– asosiyArrayBuffer. Typed arraylardan farqli o’laroq,DataViewo’zida buffer yaratmaydi. Bizda u tayyor bo’lishi kerak.byteOffset– view ning boshlanuvchi bayt pozitsiyasi (standart bo’yicha 0).byteLength– view ning bayt uzunligi (standart bo’yichabufferoxirigacha).
Masalan, bu yerda biz bir xil bufferdan turli formatlarda raqamlarni chiqaramiz:
// 4 baytli binary array, hammasi maksimal qiymat 255 ga ega
let buffer = new Uint8Array([255, 255, 255, 255]).buffer;
let dataView = new DataView(buffer);
// 0 offsetda 8-bitli raqam olish
alert( dataView.getUint8(0) ); // 255
// endi 0 offsetda 16-bitli raqam olish, u 2 baytdan iborat, birga 65535 sifatida talqin qilinadi
alert( dataView.getUint16(0) ); // 65535 (eng katta 16-bitli belgisiz int)
// 0 offsetda 32-bitli raqam olish
alert( dataView.getUint32(0) ); // 4294967295 (eng katta 32-bitli belgisiz int)
dataView.setUint32(0, 0); // 4-baytli raqamni nolga o'rnatish, shu tariqa barcha baytlarni 0 ga o'rnatish
DataView bir xil bufferda aralash formatli ma’lumotlarni saqlashda ajoyib. Masalan, juftlik ketma-ketligini (16-bitli butun son, 32-bitli float) saqlashda, DataView ularga osongina kirish imkonini beradi.
Xulosa
ArrayBuffer asosiy obyekt, belgilangan uzunlikdagi uzluksiz xotira sohasiga havola.
ArrayBuffer da deyarli har qanday operatsiya uchun bizga view kerak.
- Bu
TypedArraybo’lishi mumkin:Uint8Array,Uint16Array,Uint32Array– 8, 16 va 32 bitli belgisiz butun sonlar uchun.Uint8ClampedArray– 8-bitli butun sonlar uchun, tayinlashda ularni “siqadi”.Int8Array,Int16Array,Int32Array– belgili butun sonlar uchun (salbiy bo’lishi mumkin).Float32Array,Float64Array– 32 va 64 bitli belgili suzuvchi nuqta sonlari uchun.
- Yoki
DataView– formatni belgilash uchun usullardan foydalanadigan view, masalangetUint8(offset).
Ko’p hollarda biz to’g’ridan-to’g’ri typed arraylarni yaratamiz va ular bilan ishlaymiz, ArrayBuffer ni qopqoq ostida “umumiy maxraj” sifatida qoldiramiz. Biz unga .buffer sifatida kirishimiz va kerak bo’lsa boshqa view yaratishimiz mumkin.
Binary ma’lumotlar bilan ishlaydigan usullarning tavsiflarida ishlatiladigan yana ikkita qo’shimcha atama bor:
ArrayBufferViewbu barcha bunday view turlarining soyabon atamasi.BufferSourceArrayBufferyokiArrayBufferViewuchun soyabon atama.
Biz bu atamalarni keyingi boblarda ko’ramiz. BufferSource eng keng tarqalgan atamalardan biri, chunki u “har qanday binary ma’lumot” ni anglatadi – ArrayBuffer yoki uning ustidagi view.
Mana cheat sheet:
Izohlar
<code>yorlig'ini ishlating, bir nechta satrlar uchun - ularni<pre>yorlig'i bilan o'rab qo'ying, 10 satrdan ortiq bo'lsa - sandbox (plnkr, jsbin, codepen…)