UTF-16
az UTF-16 egy 16 bites változó hosszúságú kódolási séma, amely az UTF karakterkészletet használja a karakterkód pontokhoz. Ez azt jelenti, hogy egy UTF-16 kódolt karakter 16 bites kódegységgel rendelkezik.
mivel tudjuk, hogy egy UTF-8 kódolt karakter 1-4 kódegységben ábrázolható, az UTF-16 karakter 1 vagy 2 kódegységben ábrázolható. Ezért egy UTF-16 karakter 16 vagy 32 bit memóriát vehet igénybe a kódpontja alapján.
mielőtt beleugranánk az UTF-16 kódolási specifikációkba, értsük meg, hogyan tudjuk az UTF-16 működését.
mivel 16 bites kódegységgel rendelkezünk, elméletileg 21-et tudunk kódolni a 0 kódponttól a 65 535-ig. De mi van, ha van egy karakterünk, amelynek kódpontja nagyobb, mint 65 535? Ebben az esetben hozzáadhatunk egy másik kódegységet.
Az extra kódegységgel összesen 232 karaktert kódolhatunk, ami több mint 4M. de akkor a kérdés az, hogy egy UTF-16 dekóder honnan tudja, hogy 2 kódegységet kell figyelembe vennie egy karakter dekódolásához?
az UTF-8 úgy oldotta meg ezt a problémát, hogy az első kódegység kezdeti bitjeit és a folytató kódegységeket bizonyos bitértékekre állította, amelyeket az UTF-8 dekóder használhat arra, hogy levonja, hány kódegységet vehet fel egy karakter.
ugyanezt megtehetjük az UTF-16 kódegységgel is, de akkor fel kell áldoznunk néhány bitet egy kódegységben ehhez a funkcióhoz. Beállíthatjuk a kódegység néhány kezdeti bitjét valamilyen értelmes értékre, amelyet egy UTF-16 dekóder megérthet.
ahhoz, hogy önszinkronizáló erőt adjon a kódegységeknek, a kódegységnek meg kell tudnia mondani, hogy ez a kezdeti kódegység vagy a folytató kódegység, és nem csak egy kódegység karaktere.
tehát az Unicode úgy döntött, hogy feláldozza a kódegység kezdeti 6 bitjét, így csak 10 bit marad a kódegység kódpontjának kódolására. Ha egy karakternek 2 kódegységre van szüksége, akkor a memória 20 bitje (32 bitből vagy 4 bájtból) tartalmazza a karakter tényleges kódpont-információit.
tehát mik ezek a kezdeti bitek, és hogyan hatnak ezek a bitek az UTF karakterkészletbe? Kövessük az alábbi példát.
1101 10xx xxxx xxxx 1101 11xx xxxx xxxx
FIRST CODE UNIT---- SECOND CODE UNIT---
az UTF-16 szabvány szerint az első kódegységnek 110110₂-val, a második kódegységnek pedig 110111₂-val kell kezdődnie. Ez segít az UTF-16 dekódernek megérteni, hogy melyik az első kódegység, és melyik a második. Ez teszi az UTF-16 önszinkronizálását.
most mi van 10 bit kódegységenként játszani, mi a tartomány tudunk játszani belül? Végül hány karaktert lehet kódolni az UTF-16 kódolás két kódegységében?
ne aggódjon, csak egy kódegységben kódolt karakterekről fogunk beszélni.
ha megnézi a fenti kódegység sablonokat, akkor az 1101 1000 0000 0000-1101 1111 11111-ig terjedő tartományunk van. Ez ekvivalens a D800i-GI-vel a DFFFI-GI-vel.
az első kódegység tartománya D800jg-től 6FFFJG-ig, a második kódegység tartománya pedig DC00JG-től DFFFJG-ig terjed. Ezeket az értékeket az összes kódpont Bit be-és kikapcsolásával kaphatjuk meg.
mivel az UTF-16-nak önszinkronizálónak kell lennie, a d800i és DFFFI-gi közötti Kódpontok nem képviselhetnek karaktert az UTF-16-ban. Mivel minden UTF kódolás ugyanazt az UTF karakterkészletet követi, ezeket a kódpontokat az UTF korlátozza, és nem rendelhetők hozzá semmilyen karakterhez.
a D800i-GI és a DFFFI-gi közötti Kódpontok nem jelentenek semmilyen karaktert, ezért helyettesítő kódpontoknak nevezzük őket, vagy együtt helyettesítő pároknak is nevezzük őket.
az első helyettesítő kódpont (az első kódegységből) magas helyettesítőnek, a második kódpontnak (a második kódegységből) pedig alacsony helyettesítőnek is nevezik. Összesen 2048 kódpont, 1024 helyettesítőnként.
a helyettesítő Kódpontok feláldozták az életüket, hogy több karaktert kódolhassunk két kódegységgel. Gondolj bele!
tehát a nagy kérdés, hogy kódolhatunk-e egy karaktert egyetlen UTF-16 kódegységgel? A válasz igen. Az UTF-16 egy 16 bites változó hosszúságú kódolási séma. Tehát ez azt jelenti, hogy 21 am karaktert kódolhatunk egyetlen kódegységgel?
a válasz nem. Elméletben kódolhatnánk 21 as karaktert a 0000jpt (0jpt) kódponttal FFFFJPT (65535jpt) – re, de a d800jpt és DFFJPT közötti Kódpontok nem jelentenek semmilyen karaktert, mivel fenn vannak tartva.
ezért biztonságos kódolni a karaktereket 0000jp-től D7FFJP-ig és E000jp-től FFFFJP-ig, így 63 488 (65536-2048) karakterig. Ez csak azokra a karakterekre vonatkozik, amelyeket az UTF-16 egyetlen kódegységében lehet kódolni.
mivel összesen 20 bitet kell játszanunk, amikor a karakterekről van szó, mint amennyit az UTF-16 2 kódegységébe lehet kódolni, 22oritmus több karaktert kódolhatunk, ami 1 048 576 karakter.
tehát összesen 1 048 576 + 63 488 kódot tudunk kódolni, ami 1 112 064 karakter (több mint 1 millió karakter). Ez az UTF karakterkészlet határa. Mivel az UTF-16 képes kódolni ezeket a sok karaktert, más UTF kódolások nem képviselhetnek ezeken túlmutató karaktereket.
UTF karakterkészlet-Kódpontok
mivel tudjuk, hogy a kódpont egy karakterhez rendelt tizedes érték, mi (Unicode) nem rendelhetünk érvénytelen kódpontot egy tényleges karakterhez. Eddig Az érvénytelen Kódpontok helyettesítő Kódpontok.
egyetlen UTF-16 kódegységgel 63 488 karaktert tudunk kódolni 0000-től d7ffi-ig és E000i-tól FFFFI-ig. Az utolsó kódpont 65,535. Ezeket BMP karaktereknek nevezzük (később elmagyarázzuk).
két UTF-16 kódegységgel 1 048 576 karaktert tudunk kódolni. Mivel nem tudjuk újra indul 0 érték (kódpont) mert ezek után jönnek BMP karakterek, meg kell ellensúlyozni őket 65,536. Ezeket a karaktereket kiegészítő karaktereknek nevezzük (később elmagyarázzuk).
ezért az első kiegészítő karakter kódpontértéke 65536licc, amely egyenértékű 10000lickerrel. Mivel 1 048 576 karaktert kódolhatunk két UTF-16 kódegységgel, az utolsó kódpont az 1114111LICC, amely egyenértékű a 10FFFFI-vel.
tehát bontsuk le a dolgokat egyszerű táblázatos formában.
+-----------+---------------------+--------------------+
| UTF-16 CU | Code Point | |
+-----------+---------------------+--------------------+
| 1 | 0000₁₆ - D7FF₁₆ | valid |
+-----------+---------------------+--------------------+
| 1 | D800₁₆ - DFFF₁₆ | invalid(surrogate) |
+-----------+---------------------+--------------------+
| 1 | E000₁₆ - FFFF₁₆ | valid |
+-----------+---------------------+--------------------+
| 2 | 10000₁₆ - 10FFFF₁₆ | valid |
+-----------+---------------------+--------------------+
| | 110000₁₆ - FFFFFF₁₆ | unassigned |
+-----------+---------------------+--------------------+
ezzel a tudással nézzük meg, hogyan kódolhatunk néhány karaktert az UTF-16-ban. Válasszunk egy egyszerű ASCII karaktert a (kódpont: 41ifornic), egy karaktert a hindi (Indiai) nyelvből (ejtsd: Aa, kódpont: 906ifornic), és egy Emoticon A-t (Happy face, kódpont: 1f60aifornic).
mint a fenti táblázatból láthatjuk, mind az a, mind a 6 kódolható az UTF-16 egyetlen kódegységébe, mivel értékeik kisebbek, mint FFFFJGVERI.
Ha egy karaktert csak egy kódegységben kell kódolnunk, akkor csak a karakter kódpontját kell konvertálnunk egy 16 bites bináris számba. Az a karakterek esetében a 00000000 01000001₂ az UTF-16 ábrázolás.
Hasonlóképpen, a karakterek esetében a 906iforg kódpontját csak 16 bites bináris számra kell konvertálni, amely 00001001 00000110₂.
általában egy karakter kódegységeit ábrázoljuk hexadecimális számokban. Ezért az a karakter esetében az UTF-16 reprezentáció 0041i-t, míg a karakter esetében az UTF-16 reprezentáció 0906i-t.
a karakterek esetében a dolgok kissé eltérnek. A kódpont az 1F60AIY. Ha megnézzük a fent említett UTF-16 táblázatot, akkor azt az UTF-16 2 kódegységébe kell kódolni. Szóval hogyan kezdjük?
először ki kell vonnunk a kódpontból 10000-et. Ennek oka az, hogy az UTF-16 2 kódegységében kódolt minden karakter a BMP karakterek után jött, amelyek Utolsó kódpontja az FFFFJGARI.
ezért ahhoz, hogy megkapjuk a kódoláshoz használt bitek tényleges értékét (ami 20 a 2 kódegységben), ki kell vonnunk a kódpontból 10000jgv-t, és a végső számot kell használnunk a 20 bit előállításához.
a jobb megértés érdekében az UTF-16 2 kódegységével ábrázolt első karakternek mind a 20 bitje 0 lesz. Tehát a karakter kódpontjának kódolásához használt bitek értéke 0. De még mindig, a kódpont 10000ifornia szerint Unicode karakterkészlet. Ennek oka az, hogy az e 20 Bit által kapott értéket hozzáadjuk az 10000iforgar-hoz, hogy létrehozzuk a végső kódpontot.
mint korábban láttuk, ez a 2 kódegység az alábbiak szerint néz ki.
1101 10xx xxxx xxxx 1101 11xx xxxx xxxx
FIRST CODE UNIT---- SECOND CODE UNIT---
csak ki kell töltenünk ezt a 20 bitet (x
) a karakterkód ponttól kapott értékkel. A kódpont a karakter 60a5peri. De először ki kell vonnunk belőle az 10000ifort. Megkapjuk az F60AIY-t.
most át kell alakítanunk az F60A9PERIT egy 20 bites bináris számra, és ki kell töltenünk a fenti kódegység sablon 20 bitjét. A binárisan F60AIPULIN értéke 0000111101 1000001010₂. Most kitölthetjük ezt a 20 helyőrző bitet.
Az alábbiakban a végső kódegységek találhatók.
1101 1000 0011 1101 1101 1110 0000 1010
0xD83D 0xDE0A
a gyors módja annak, hogy ellenőrizze, hogy ezek a kódegységek érvényesek-e, és valóban ezek a helyettesítő párok képesek-e képviselni a kódolt karaktert, nyisson meg egy böngésző DevTool-ot, és írja be a console.log('\uD83D\uDE0A');
a konzolba.