UTF-16
UTF-16 is een 16-bit variabele lengte coderingsschema en het gebruikt de UTF tekenset voor tekencodepunten. Dit betekent dat een UTF-16 gecodeerd teken een 16-bit code eenheid zal hebben.
omdat we weten dat een UTF-8 gecodeerd teken kan worden weergegeven in 1 tot 4 code-eenheden, kan een UTF-16-teken worden weergegeven in 1 of 2 code-eenheden. Vandaar kan een UTF-16 karakter 16 of 32 beetjes geheugen nemen die op zijn codepunt worden gebaseerd.
voordat u in de UTF-16-coderingsspecificaties springt, laten we begrijpen hoe we UTF-16 kunnen laten werken.
omdat we 16-bits code-eenheid hebben, kunnen we in theorie 21⁶-tekens coderen van codepunt 0 tot 65.535. Maar wat als we een karakter hebben met het codepunt groter dan 65.535? In dat geval kunnen we een andere code-eenheid toevoegen.
met de extra code-eenheid kunnen we in totaal 232 tekens coderen, wat meer is dan 4M. maar dan is de vraag hoe een UTF-16 decoder weet dat hij 2 code-eenheden moet overwegen om een teken te decoderen?
UTF-8 loste dit probleem op door initiële bits van de eerste code-eenheid en continuation code-eenheden in te stellen op een aantal specifieke bit-waarden die een UTF-8 decoder kan gebruiken om af te trekken hoeveel code-eenheden een karakter kan nemen.
we kunnen hetzelfde doen met de UTF-16 code eenheid, maar dan moeten we enkele bits in een code eenheid opgeven voor deze functie. We kunnen enkele initiële bits van een code-eenheid instellen op een betekenisvolle waarde die een UTF-16 decoder kan begrijpen.
ook om zelfsynchroniserend vermogen te geven aan codeeenheden, moet een codeeenheid kunnen vertellen of het de initiële codeeenheid of een vervolgcodeeenheid is en niet een teken van slechts één codeeenheid.
dus besloot Unicode om de initiële 6 bits van de code-eenheid op te offeren, waardoor er slechts 10 bits overblijven om het codepunt van een teken per code-eenheid te coderen. Als een teken 2 codeeenheden nodig heeft, bevat 20 bits van het geheugen (van 32 bits of 4 bytes) de werkelijke codepuntinformatie van het teken.
dus wat zijn deze initiële bits en hoe deze bits een deuk maken in de UTF-tekenset? Laten we het onderstaande voorbeeld volgen.
1101 10xx xxxx xxxx 1101 11xx xxxx xxxx
FIRST CODE UNIT---- SECOND CODE UNIT---
vanaf de UTF-16-standaard moet de eerste code-eenheid beginnen met 110110₂ en de tweede code-eenheid moet beginnen met 110111₂. Dit zal een UTF-16 decoder helpen om te begrijpen welke als de eerste code eenheid en welke is de tweede. Dit maakt UTF-16 self-synchronizing.
nu wat we hebben 10 bits per code eenheid om mee te spelen, Wat is het bereik dat we kunnen spelen binnen? Uiteindelijk, hoeveel tekens kunnen worden gecodeerd in twee code-eenheden van UTF-16 codering?
maak je geen zorgen, we zullen het hebben over tekens die gecodeerd zijn in slechts één code-eenheid.
Als u de bovenstaande code-eenheidssjablonen bekijkt, hebben we een bereik van 1101 1000 0000 0000₂ tot 1101 1111 1111 1111₂. Dat is gelijk aan D800₁₆ aan dfff₁₆.
💡 de eerste codeeenheid heeft een bereik van D800₁₆ tot 6fff₁₆ en de tweede codeeenheid heeft een bereik van dc00₁₆ tot DFFF₁₆. We kunnen deze waarden krijgen door alle Codepunten bits aan en uit te zetten.
aangezien UTF-16 zelfsynchroniserend moet zijn, mogen Codepunten tussen D800₁₆ en dfff₁₆ geen teken in UTF-16 vertegenwoordigen. Aangezien alle UTF-coderingen dezelfde UTF-tekenset volgen, worden deze Codepunten beperkt door UTF en worden ze niet en zullen ze niet worden toegewezen aan tekens⁰.
Codepunten tussen D800₁₆ en dfff₁₆ vertegenwoordigen geen tekens, vandaar dat ze surrogaatcodepunten worden genoemd of samen worden ze ook wel surrogaatparen⁰ genoemd.
het eerste surrogaatcodepunt (van de eerste codeeenheid) ook wel hoog surrogaatpunt genoemd en het tweede codepunt (van de tweede codeeenheid) ook wel laag surrogaatpunt genoemd. Dat maakt het totaal van 2048 Codepunten, 1024 per draagmoeder.
💁 ♂ surrogaatcodepunten offerden hun leven op zodat we meer tekens konden coderen met twee codeeenheden. Denk daar eens over na!
dus de grote vraag, kunnen we een teken coderen met een enkele code eenheid van UTF-16? Het antwoord is ja. UTF-16 is een 16-bit variabele lengte codering schema. Dus betekent dat, we kunnen coderen 21 characters tekens met een enkele code eenheid?
het antwoord is nee. In theorie, kunnen we coderen 21⁶ tekens met code punt 0000₁₆ (0₁₀) te FFFF₁₆ (65535₁₀), maar de code-punten tussen D800₁₆ en DFFF₁₆ vertegenwoordigen niet alle karakters zoals ze zijn voorbehouden.
daarom is het veilig om tekens te coderen van 0000₁₆ tot d7ff₁₆ en E000₁₆ tot Ffff₁₆ waardoor er 63.488 (65536-2048) tekens overblijven. Dit is alleen voor de tekens die kunnen worden gecodeerd in slechts één code-eenheid van UTF-16.
omdat we in totaal 20 bits hebben om mee te spelen als het gaat om karakters dan gecodeerd kan worden in 2 code-eenheden van UTF-16, kunnen we 22⁰ meer karakters coderen, wat 1.048.576 karakters is.
dus in totaal kunnen we 1,048,576 + 63,488 coderen wat neerkomt op 1,112,064 tekens (meer dan 1miljoen tekens). Dit is de limiet van de UTF-tekenset. Omdat UTF-16 Deze vele karakters kan coderen, kunnen andere UTF-coderingen geen karakters voorstellen die verder gaan dan deze.
UTF charset Codepunten
omdat we weten dat een codepunt een decimale waarde is die aan een teken is toegewezen, mogen we (Unicode) geen ongeldig codepunt toewijzen aan een feitelijk teken. Tot nu toe zijn de ongeldige Codepunten surrogaat Codepunten.
met slechts een enkele UTF-16 code-eenheid, kunnen we 63.488 tekens coderen, variërend van 0000₁₆ tot d7ff₁₆ en E000₁₆ tot Ffff₁₆. Het Laatste codepunt is 65.535. Deze worden BMP-tekens genoemd (later uitgelegd).
Met Twee code-eenheden van UTF-16 kunnen we 1.048.576 tekens coderen. Omdat we niet opnieuw kunnen beginnen met 0 waarde (codepunt) omdat deze na BMP tekens komen, moeten we ze compenseren met 65,536. Deze karakters worden aanvullende karakters genoemd (later uitgelegd).
daarom heeft het eerste aanvullende teken een codepuntwaarde van 65536₁₀, wat gelijk is aan 10000₁₆. Aangezien we 1,048,576 tekens kunnen coderen met twee code-eenheden van UTF-16, is het laatste codepunt 1114111₁₀ wat gelijk is aan 10ffff₁₆.
dus laten we de dingen opsplitsen in een eenvoudige tabelvorm.
+-----------+---------------------+--------------------+
| 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 |
+-----------+---------------------+--------------------+
Met deze kennis, laten we eens kijken hoe we sommige tekens in UTF-16 kunnen coderen. Laten we een eenvoudig ASCII-teken a (codepunt: 41₁₆), een teken uit Hindi (Indiase) taal आ (uitgesproken als AA, codepunt: 906₁₆) en een emoticon 😊 (genoemd als Happy Face, codepunt: 1f60a₁₆) kiezen.
zoals we uit de bovenstaande tabel kunnen zien, kunnen zowel A Als आ worden gecodeerd in slechts één code-eenheid van UTF-16 omdat hun waarden kleiner zijn dan FFFF₁₆.
wanneer we een teken in slechts één code-eenheid moeten coderen, hoeven we alleen het codepunt van het teken in een 16-bits binair getal te converteren. Voor de tekens A is 00000000 01000001₂ de UTF-16 representatie.
evenzo, voor het karakter आ, hoeven we alleen maar het codepunt 906₁₆ te converteren naar een 16-bits binair getal dat 00001001 00000110₂ is.
normaal gesproken vertegenwoordigen we code-eenheden van een teken in hexadecimale getallen. Daarom is voor teken a de UTF-16 representatie 0041₁₆ en op dezelfde manier is voor het teken UTF-16 representatie आ 0906₁₆.
voor het teken 😊 zijn de dingen een beetje anders. Het codepunt is 1F60A₁₆. Als we kijken naar de UTF-16 tabel hierboven, het moet worden gecodeerd in 2 code eenheden van UTF-16. Hoe beginnen we?
eerst moeten we 10000₁₆ aftrekken van het codepunt. De reden hiervoor is dat elk teken gecodeerd in 2 code-eenheden van UTF-16 na de BMP-tekens komt waarvan het laatste codepunt FFFF₁₆ is.
om de werkelijke waarde te krijgen van bits die gebruikt worden voor codering (dat is 20 in 2 codeeenheden), moeten we 10000₁₆ aftrekken van het codepunt en het uiteindelijke getal gebruiken om deze 20 bits te genereren.
💡 om u te helpen beter te begrijpen, zal het eerste teken vertegenwoordigd met 2 code-eenheden van UTF-16 al zijn 20 bits op 0 gezet hebben. Dus de waarde van de bits die gebruikt worden om het codepunt van dit teken te coderen is 0. Maar toch is het codepunt 10000₁₆ volgens Unicode-tekenset. Dit is omdat de waarde die door deze 20 beetjes wordt opgebracht aan 10000₁₆ wordt toegevoegd om het definitieve codepunt te genereren.
zoals eerder gezien, zien deze 2 code-eenheden er hieronder uit.
1101 10xx xxxx xxxx 1101 11xx xxxx xxxx
FIRST CODE UNIT---- SECOND CODE UNIT---
We hoeven alleen deze 20 bits (x
) te vullen met de waarde die wordt ontvangen van het tekencodepunt. Het codepunt van het teken 😊is 1F60A₁₆. Maar eerst moeten we er 10000₁₆ van Aftrekken. We krijgen F60A₁₆.
nu moeten we f60a₁₆ converteren naar een 20-bits binair getal en de 20 bits in de bovenstaande code eenheid template vullen. F60A₁₆ in binair is 0000111101 1000001010₂. Nu kunnen we deze 20 plaatshouders vullen.
hieronder staan de uiteindelijke code-eenheden.
1101 1000 0011 1101 1101 1110 0000 1010
0xD83D 0xDE0A
de snelle manier om te controleren of deze code-eenheden geldig zijn en in feite of deze surrogaatparen het gecodeerde teken kunnen vertegenwoordigen, open een Browser DevTool en voer console.log('\uD83D\uDE0A');
in de console.