Introduktion til tegnkodning

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.

(Chrome udviklerværktøjer)

Du kan også bruge dette online værktøj til at generere UTF-16 kodepunkter.

Unicode Character Planes

et plan er en kontinuerlig gruppe på 21 ads eller 65.536 kodepunkter. Da UTF-16 har begrænset kodepunkter til et maksimum på 10fffffrjg, har vi i alt 17 tegn fly i Unicode standard startende fra 0 til 16.

da 21-tegn kan defineres af den enkelte kodeenhed i UTF-16 (inklusive surrogatkodepunkter), danner den det første (0.) plan. Dette plan indeholder næsten alle tegn på grundlæggende sprog rundt om i verden. Dette er grunden til, at dette plan kaldes det grundlæggende flersprogede plan eller BMP.

Dernæst har vi kodepunkter defineret af to kodeenheder af UTF-16. Disse indeholder 22⁰ tegn, da vi har 20 bits til at kode kodepunktsværdien. Disse er opdelt i 16 fly (2 i træk 21 i træk). Disse kaldes supplerende fly.

Lira For mere information om disse fly, Læs dette dokument.

sammenligning med UCS-2

UCS-2 er en 16-bit kodning med fast bredde. Det betyder, at kun en 16-bit kodeenhed bruges til at repræsentere et kodepunkt. I teorien kan UCS-2 repræsentere 21 forskellige tegn, men der er en vri.

vi bruger udtrykket kodeenhed i denne kodning med fast bredde til at forstå forholdet mellem UTF-16. I virkeligheden er der ikke noget som kodeenhed i nogen fast med kodning.

da UCS følger Unicode-tegnsættet, er kodningen af tegnene i UCS-2 identisk med kodningen af tegnene i UTF-16, som er repræsenteret i kun en kodeenhed.

Kris da UCS følger Unicode-tegnsættet, kan det ikke kode et gyldigt tegn med de kodepunkter, der er reserveret til surrogaterne.

så i nøddeskal indeholder UCS-2 tegnene i det grundlæggende flersprogede plan. Dette er grunden til, at nogle ældre dokumenter og programmer brugte UCS-2-kodning. Men UCS-2-kodning er blevet forældet, og UTF-16 foretrækkes.

Endianness og BOM

som vi diskuterede Før, indeholder en UTF-kodede dokumenter på et lavt niveau sekvensen af kodeenheder. For UTF-8 er kodeenheden 8 bit lang, mens den for UTF-16 er 16 bit lang. Disse kodeenheder udgør tegnene.

en UTF-8 eller UTF-16 dekoder læser kodeenhederne sekventielt, en kodeenhed ad gangen for at generere tegnene.

hver kodeenhed repræsenterer en numerisk værdi, som en UTF-8 eller UTF-16 dekoder kan se på og beslutte, om det er tilstrækkeligt at repræsentere et tegn, eller det følger andre kodeenheder, der også skal overvejes.

når det kommer til UTF-8, er tingene enkle. Da hver kodeenhed er 8 bit lang, er det hurtigt og nemt at konvertere det 8-bit binære tal til en numerisk værdi. Dette er dog ikke tilfældet med UTF-16.UTF-16 kode enhed er en 16-bit (2 bytes) binært tal, der repræsenterer en kode punktværdi. At generere den numeriske værdi fra flere bytes er generelt vanskelig, og forskellige systemer opfører sig forskelligt.

denne adfærd afhænger af systemets endianness. Fra vores tidligere diskussion om endianness er der to måder, vi kan skrive en UTF-16 kode enhedsværdi. Enten i Big-endian format eller Little-endian format.

i Big-endian format gemmes MSB først, og LSB gemmes sidst. Indtil videre skriver vi UTF-16-kodeenhedens værdi i Big-endian-formatet. For at skrive UTF-16 kode enhedsværdi i Little-endian, skal vi bytte bytes.

lad os tale om karakterkrus. Fra det tidligere eksempel kan det repræsenteres i kun en kodeenhed af UTF-16, og dens kodning i seksadecimal repræsentation ser ud som 0906frh.

0906frg er et 16-bit tal, hvor 09 er MSB og 06 er LSB. Derfor i Big-endian arkitektur, vil det blive gemt som 09 06. Men i en lille endian arkitektur vil den blive gemt som 06 09.

derfor bliver det vores ansvar at kode tegn ved at tage systemets endianness i tankerne, så systemet kan læse et UTF-16-dokument korrekt.

men hvordan kan vi på forhånd fortælle, om en brugers maskine er kompatibel med det kodede dokument eller ej? Og da et systems endianness kan påvirke, hvordan et dokument afkodes, Hvordan deler vi det offentligt?

det er her BOM kommer ind i billedet. Et byte-Ordremærke (BOM) er en byte-sekvens, der tilføjes i begyndelsen af en tekstfil eller tekstdata.

Unicode anbefaler, at tegn med kodepunkt FEFFFLERE til at fungere som en stykliste for UTF-16 og UTF-32 kodninger. Denne karakter skal før dokumentets første tegn. Denne karakter vil dog ikke blive overvejet af dekoderen i output.

dette tegn (U + FEFF) er et nul-bredde ikke-brydende rum (VNBSP) tegn, og det er usynligt. Derfor, selvom en dekoder ikke genkender Styklisten, producerer den ikke noget synligt output.

dette tegn er repræsenteret i en enkelt kode enhed af UTF-16 og i seksadecimal repræsentation det ligner FE (MSB) og FF (LSB).

derfor når tegn er kodet i Big-endian format, skal vi tilføje FEFF som styklisten i begyndelsen af filen, og når tegn er kodet i Little-endian format, skal vi tilføje FFFE (reverse) som styklisten i begyndelsen af filen.

Unicode anbefaler at tilføje Styklisten til UTF-16 kodet dokument. Men hvis Styklisten mangler, antages Big-endian-format.

IANA foretrækker UTF-16 som identifikator for at betegne et UTF-16-kodet dokument. UTF-16be bruges dog til dokument kodet i Big-endian-format, og UTF-16le bruges til Little-endian-format.

når UTF-16be eller UTF-16le navn bruges, anbefales BOM ikke at blive prepended til en fil. Selv i dette tilfælde, hvis Styklisten er tilføjet, vil den blive betragtet som et tegn, og det vil ikke blive ignoreret.

lit UTF-16, UTF-16be og UTF-16le navne er store og små bogstaver.

fordele og ulemper

UTF-16 er effektiv, fordi den kun har 2 kodeenheder, og da de fleste brugte tegn falder i BMP-sættet, kan de repræsenteres i kun en kodeenhed. Det kommer dog med mange problemer.

den største ulempe ved UTF-16 er, at den ikke er ASCII-kompatibel. Da ASCII-tegn er kodet med en enkelt kodeenhed (16-bit nummer), kan de ikke afkodes korrekt af en ASCII-dekoder.UTF-16 bruger unødvendig plads til ASCII-tegn. Sammenlignet med det UTF-8-kodede dokument, der kun indeholder ASCII-tegn, er størrelsen på det samme dokument kodet i UTF-16 to gange større.

UTF-16 bliver også påvirket af systemets endianness. Hvis Styklisten mangler, og der ikke bruges en passende kodningsidentifikator (som UTF-16LE), kan et UTF-16-kodet dokument muligvis ikke afkodes korrekt.

på grund af karakteren af UTF-16-kodning har den introduceret surrogatkodepunkter, der ikke kan repræsentere de gyldige tegn. Det har også begrænset Unicode-tegnsættet til 10ffffashih (sidste kodepunkt).

På trods af disse fakta er nogle af programmeringssprogene som JavaScript, Java osv. og systemer som vinduer foretrækker UTF-16-kodning.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.