UTF-16
UTF-16 er et 16-bit kodningsskema med variabel længde, og det bruger UTF-tegnsættet til tegnkodepunkter. Dette betyder, at et UTF-16-kodet tegn vil have en 16-bit kodeenhed.
da vi ved, at et UTF-8-kodet tegn kan repræsenteres i 1 til 4 kodeenheder, kan et UTF-16-tegn repræsenteres i 1 eller 2 kodeenheder. Derfor kan et UTF-16-tegn tage 16 eller 32 bit hukommelse baseret på dets kodepunkt.
før vi hopper ind i UTF-16-kodningsspecifikationerne, lad os forstå, hvordan vi kan få UTF-16 til at fungere.
da vi har 16-bit kodeenhed, kan vi i teorien kode 21-tegn fra kodepunkt 0 til 65.535. Men hvad nu hvis vi har et tegn med kodepunktet større end 65.535? I så fald kan vi tilføje en anden kodeenhed.
med den ekstra kodeenhed kan vi kode i alt 232 tegn, hvilket er mere end 4m. men så er spørgsmålet, hvordan en UTF-16 dekoder vil vide, at den skal overveje 2 kodeenheder for at afkode et tegn?
UTF-8 løste dette problem ved at indstille indledende bits af den første kodeenhed og fortsættelseskodeenheder til nogle specifikke bitværdier, som en UTF-8-dekoder kan bruge til at fratrække, hvor mange kodeenheder et tegn kan tage.
Vi kan gøre det samme med UTF-16 kode enhed, men så er vi nødt til at ofre nogle bits i en kode enhed for denne funktion. Vi kan indstille nogle indledende bits af en kodeenhed til en meningsfuld værdi, som en UTF-16-dekoder kan forstå.
også for at give selvsynkroniserende effekt til kodeenheder skal en kodeenhed være i stand til at fortælle, om det er den oprindelige kodeenhed eller en fortsættelseskodeenhed og ikke et tegn på kun en kodeenhed.så Unicode besluttede at ofre de første 6 bit af kodeenheden og efterlod kun 10 bit for at kode kodepunktet for et tegn pr. Hvis et tegn har brug for 2 kodeenheder, indeholder 20 bit af hukommelsen (ud af 32 bit eller 4 bytes) den faktiske kodepunktsinformation for tegnet.
så hvad er disse indledende bits, og hvordan disse bits gør en bule i UTF-tegnsættet? Lad os følge nedenstående eksempel.
1101 10xx xxxx xxxx 1101 11xx xxxx xxxx
FIRST CODE UNIT---- SECOND CODE UNIT---
fra UTF-16-standarden skal den første kodeenhed starte med 110110₂, og den anden kodeenhed skal starte med 110111₂. Dette vil hjælpe en UTF-16-dekoder til at forstå, hvilken hvis den første kodeenhed og hvilken er den anden. Dette gør UTF-16 selvsynkronisering.
Hvad har vi nu 10 bits pr. kodeenhed at lege med, hvad er det interval, vi kan spille inden for? I sidste ende, hvor mange tegn kan kodes i to kodeenheder af UTF-16-kodning?
bare rolig, vi vil tale om tegn kodet i kun en kodeenhed.
Hvis du kigger på ovenstående kodeenheds skabeloner, har vi en rækkevidde fra 1101 1000 0000 0000₂ til 1101 1111 1111 1111₂. Det svarer til D800frh til DFFFFRHRH.
den første kodeenhed har et interval fra D800-til 6fff-til og med den anden kodeenhed fra DC00-til DFFF-til. Vi kan få disse værdier ved at dreje alle kodepunkter bits : til og fra.
da UTF-16 skal være selvsynkroniserende, må kodepunkter mellem D800-er og DFFF-er ikke repræsentere et tegn i UTF-16. Da alle UTF-kodninger følger det samme UTF-tegnsæt, er disse kodepunkter begrænset af UTF, og de er ikke Og vil ikke blive tildelt nogen tegn.
kodepunkter mellem D800strg og DFFFSTRGG repræsenterer ikke nogen tegn, derfor kaldes de surrogatkodepunkter, eller sammen kaldes de også som surrogatpar.
det første surrogatkodepunkt (fra første kodeenhed) kaldes også som højt surrogat og andet kodepunkt (fra anden kodeenhed) kaldes også som lavt surrogat. Gør det samlede antal 2048 kodepunkter, 1024 pr.
basisk surrogatkodepunkter ofrede deres liv, så vi kunne kode flere tegn med to kodeenheder. Tænk over det!
så det store spørgsmål, kan vi kode et tegn med en enkelt kodeenhed af UTF-16? Svaret er ja. UTF-16 er et 16-bit kodningsskema med variabel længde. Så betyder det, at vi kan kode 21-tegn med en enkelt kodeenhed?
svaret er nej. I teorien kunne vi kode 21-tegn med kodepunkt 0000-ilter (0-ilter) til FFFF-ilter (65535-ilter), men kodepunkter mellem D800-ilter og DFFF-ilter repræsenterer ikke nogen tegn, da de er reserveret.
derfor er det sikkert at kode tegn fra 0000-Å til D7FF-Å og E000-Å til FFFF-Å-Å, som tegner sig for 63.488 (65536-2048) tegn. Dette er kun for de tegn, der kan kodes i kun en kodeenhed af UTF-16.
da vi har i alt 20 bits at lege med, når det kommer til tegn, end der kan kodes i 2 kodeenheder af UTF-16, kan vi kode 22⁰ flere tegn, hvilket er 1.048.576 tegn.
så i alt kan vi kode 1.048.576 + 63.488, hvilket svarer til 1.112.064 tegn (mere end 1million tegn). Dette er grænsen for UTF-tegnsættet. Da UTF-16 kan kode disse mange tegn, kan andre UTF-kodninger ikke repræsentere tegn ud over disse.
UTF charset Code Points
da vi ved, at et kodepunkt er en decimalværdi tildelt et tegn, må vi (Unicode) ikke tildele et ugyldigt kodepunkt til et faktisk tegn. Indtil videre er de ugyldige kodepunkter surrogatkodepunkter.
med kun en enkelt UTF-16-kodeenhed kan vi kode 63.488 tegn, der spænder fra 0000frg til D7FFFRG og E000frg til ffffrfrg. Det sidste kodepunkt er 65.535. Disse kaldes BMP-tegn (forklaret senere).
med to kodeenheder på UTF-16 kan vi kode 1.048.576 tegn. Da vi ikke igen kan starte fra 0 værdi (kodepunkt), fordi disse kommer efter BMP-tegn, skal vi udligne dem med 65.536. Disse tegn kaldes supplerende tegn (forklaret senere).
derfor har det første supplerende tegn en kodepunktsværdi på 65536frelj, hvilket svarer til 10000frelj. Da vi kan kode 1.048.576 tegn med to kodeenheder af UTF-16, er det sidste kodepunkt 1114111frj, hvilket svarer til 10FFFFFRJD.
så lad os nedbryde ting i en simpel tabelform.
+-----------+---------------------+--------------------+
| 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 |
+-----------+---------------------+--------------------+
Med denne viden, lad os se, hvordan vi kan kode nogle tegn i UTF-16. Lad os vælge et simpelt ASCII-tegn A (kodepunkt: 41frør), et tegn fra Hindi (Indisk) sprogkrus (udtalt som Aa, kodepunkt: 906frør) og et humørikonfrør (kaldet Happy face, kodepunkt: 1f60afrørør).
som vi kan se fra ovenstående tabel, kan både A og Krar kodes i kun en kodeenhed af UTF-16, da deres værdier er mindre end FFFFFRARIGT.
når vi skal kode et tegn i kun en kodeenhed, skal vi bare konvertere tegnets kodepunkt i et 16-bit binært tal. For tegnene A er 00000000 01000001₂ UTF-16-repræsentationen.
på samme måde skal vi bare konvertere dets kodepunkt 906frh til et 16-bit binært tal, som er 00001001 00000110₂.
normalt repræsenterer vi kodeenheder af et tegn i seksadecimale tal. Derfor for karakter A er UTF-16-repræsentationen 0041frk, og på samme måde for karakteren er UTF-16-repræsentationen Krk 0906frkrk.
for karakteren Kristian er tingene lidt anderledes. Dens kodepunkt er 1f60afl. Hvis vi ser på UTF-16-tabellen nævnt ovenfor, skal den kodes i 2 kodeenheder af UTF-16. Så hvordan begynder vi?
for det første skal vi trække 10000frh fra kodepunktet. Årsagen til det er, at hvert tegn kodet i 2 kodeenheder af UTF-16 er kommet efter BMP-tegnene, hvis sidste kodepunkt er FFFFFARE.
for at få den faktiske værdi af bits, der bruges til kodning (som er 20 i 2 kodeenheder), er vi nødt til at trække 10000er fra kodepunktet og bruge det endelige tal til at generere disse 20 bits.
for at hjælpe dig med at forstå bedre, vil det første tegn repræsenteret med 2 kodeenheder af UTF-16 have alle sine 20 bits sat til 0. Så værdien af de bits, der bruges til at kode kodepunktet for dette tegn, er 0. Men stadig er dens kodepunkt 10000flhh ifølge Unicode tegnsæt. Dette skyldes, at den værdi, som disse 20 bit giver, føjes til 10000-Ion for at generere det endelige kodepunkt.
Som set tidligere ser disse 2 kodeenheder ud som nedenfor.
1101 10xx xxxx xxxx 1101 11xx xxxx xxxx
FIRST CODE UNIT---- SECOND CODE UNIT---
Vi skal bare udfylde disse 20 bits (x
) med værdien modtaget fra tegnkodepunktet. Kodepunktet for karakteren Kristian er 1F60A-IR. Men først, Vi er nødt til at trække 10000er fra det. Vi får F60A videre.
nu er vi nødt til at konvertere F60AISER til et 20-bit binært tal og udfylde 20 bits i ovenstående kodeenheds skabelon. F60a i binær er 0000111101 1000001010₂. Nu kan vi udfylde disse 20 pladsholderbits.
nedenfor er de endelige kodeenheder.
1101 1000 0011 1101 1101 1110 0000 1010
0xD83D 0xDE0A
den hurtige måde at kontrollere, om disse kodeenheder er gyldige, og faktisk om disse surrogatpar kan repræsentere det kodede tegn, skal du åbne en bro.ser DevTool og indtasteconsole.log('\uD83D\uDE0A');
i konsollen.