Introducere în codificarea caracterelor

UTF-16

UTF-16 este o schemă de codificare cu lungime variabilă pe 16 biți și folosește setul de caractere UTF pentru punctele de cod de caractere. Aceasta înseamnă că un caracter codificat UTF-16 va avea o unitate de cod pe 16 biți.după cum știm că un caracter codificat UTF-8 poate fi reprezentat în 1 până la 4 unități de cod, un caracter UTF-16 poate fi reprezentat în 1 sau 2 unități de cod. Prin urmare, un caracter UTF-16 poate lua 16 sau 32 de biți de memorie pe baza punctului său de cod.

înainte de a sări în specificațiile de codificare UTF-16, Să înțelegem cum putem face UTF-16 să funcționeze.

Din moment ce avem unitate de cod pe 16 biți, în teorie, putem codifica 21 de caractere de la punctul de cod 0 la 65.535. Dar dacă avem un personaj cu punctul de cod mai mare de 65.535? În acest caz, putem adăuga o altă unitate de cod.

cu unitatea de cod suplimentar, putem codifica un total de 232 de caractere, care este mai mult de 4M. dar atunci întrebarea este, cum un decodor UTF-16 va ști că trebuie să ia în considerare 2 unități de cod pentru a decoda un caracter?

UTF-8 A rezolvat această problemă setând biți inițiali ai primei unități de cod și unități de cod de continuare la unele valori specifice de biți pe care un decodificator UTF-8 le poate utiliza pentru a deduce câte unități de cod poate lua un caracter.

putem face același lucru cu unitatea de cod UTF-16, dar apoi trebuie să sacrificăm câțiva biți într-o unitate de cod pentru această caracteristică. Putem seta câțiva biți inițiali ai unei unități de cod la o valoare semnificativă pe care o poate înțelege un decodificator UTF-16.

De asemenea, pentru a da putere de auto-sincronizare unităților de cod, o unitate de cod trebuie să poată spune dacă este unitatea de cod inițială sau o unitate de cod de continuare și nu un caracter al unei singure unități de cod.deci, Unicode a decis să sacrifice primii 6 biți ai unității de cod, lăsând doar 10 biți pentru a codifica punctul de cod al unui caracter pe unitate de cod. Dacă un caracter are nevoie de 2 unități de cod, 20 de biți din memorie (din 32 de biți sau 4 octeți) conține informațiile reale despre punctul de cod al caracterului.

deci, ce sunt acești biți inițiali și modul în care acești biți fac o adâncitură în setul de caractere UTF? Să urmăm exemplul de mai jos.

1101 10xx xxxx xxxx 1101 11xx xxxx xxxx
FIRST CODE UNIT---- SECOND CODE UNIT---

din standardul UTF-16, prima unitate de cod ar trebui să înceapă cu 110110₂, iar a doua unitate de cod ar trebui să înceapă cu 110111₂. Acest lucru va ajuta un decodor UTF-16 Să înțeleagă care dintre ele este prima unitate de cod și care este a doua. Acest lucru face ca UTF-16 să se auto-sincronizeze.acum, ceea ce avem 10 biți pe unitate de cod pentru a juca cu, ceea ce este gama putem juca în? În cele din urmă, câte caractere pot fi codificate în două unități de cod de codificare UTF-16?

nu vă faceți griji, vom vorbi despre caractere codificate într-o singură unitate de cod.

dacă aruncați o privire la șabloanele de unități de cod de mai sus, avem o gamă de la 1101 1000 0000 0000₂ la 1101 1111 1111 1111₂. Acest lucru este echivalent cu D800cd la DFFFCD.

XV prima unitate de cod are o gamă de la D800cd la 6FFCD, iar a doua unitate de cod are o gamă de la DC00CD la DFFCD. Putem obține aceste valori prin rotirea tuturor punctelor de cod biți: on și off.

deoarece UTF-16 trebuie să se auto-sincronizeze, punctele de cod dintre D800bh și DFFFBH nu trebuie să reprezinte un caracter în UTF-16. Deoarece toate codificările UTF urmează același set de caractere UTF, aceste puncte de cod sunt restricționate de UTF și nu sunt și nu vor fi atribuite niciunui caracter.

punctele de cod între D800cd și DFFFCD nu reprezintă caractere, prin urmare sunt numite puncte de cod surogat sau împreună sunt numite și perechi surogat.

primul punct de cod surogat (de la prima unitate de cod) numit și surogat ridicat și al doilea punct de cod (de la a doua unitate de cod) numit și surogat scăzut. Efectuarea totală a punctelor de cod 2048, 1024 pe surogat.

punctele de cod surogat de la un cod la altul și-au sacrificat viețile astfel încât să putem codifica mai multe caractere cu două unități de cod. Gândește-te la asta!

deci, marea întrebare, putem codifica un caracter cu o singură unitate de cod de UTF-16? Răspunsul este da. UTF-16 este o schemă de codificare de lungime variabilă pe 16 biți. Deci, asta înseamnă, putem codifica 21 de caractere de cod cu o singură unitate de cod?

răspunsul este nu. În teorie, am putea codifica 21 de caractere de cod cu punctul de cod 0000drah (0drah) la FFFDRAH (65535drah), dar punctele de cod între D800drah și DFFFDRAH nu reprezintă niciun caracter, deoarece sunt rezervate.

prin urmare, este sigur de a codifica caractere de la 0000cd la D7FFCD și E000cd la ffffcd lăsând care Conturi la 63,488 (65536-2048) caractere. Aceasta este doar pentru caracterele care pot fi codificate într-o singură unitate de cod a UTF-16.

Din moment ce avem un total de 20 de biți pentru a juca cu atunci când vine vorba de caractere decât pot fi codificate în 2 unități de cod de UTF-16, putem codifica 22⁰ mai multe caractere, care este 1,048,576 caractere.

Deci, în total, putem codifica 1.048.576 + 63.488 care se ridică la 1.112.064 de caractere (mai mult de 1 milion de caractere). Aceasta este limita setului de caractere UTF. Deoarece UTF-16 poate codifica aceste multe caractere, alte codificări UTF nu pot reprezenta caractere dincolo de acestea.

UTF charset code Points

după cum știm că un punct de cod este o valoare zecimală atribuită unui caracter, Noi (Unicode) nu trebuie să atribuim un punct de cod nevalid unui caracter real. Până în prezent, punctele de cod nevalide sunt puncte de cod surogat.

cu doar o singură unitate de cod UTF-16, putem codifica 63.488 de caractere variind de la 0000drah la D7FFDRAH și E000drah la FFFDRAH. Ultimul punct de cod este 65.535. Acestea se numesc caractere BMP (explicate mai târziu).

cu două unități de cod UTF-16, putem codifica 1.048.576 de caractere. Deoarece nu putem porni din nou de la valoarea 0 (punct de cod), deoarece acestea vin după caractere BMP, trebuie să le compensăm cu 65.536. Aceste caractere sunt numite caractere suplimentare (explicate mai târziu).

prin urmare, primul caracter suplimentar are o valoare de punct de cod de 65536bh, care este echivalent cu 10000bh. Deoarece putem codifica 1.048.576 de caractere cu două unități de cod de UTF-16, ultimul punct de cod este 1114111bh, care este echivalent cu 10ffffbh.

deci, să descompunem lucrurile într-o formă tabelară simplă.

+-----------+---------------------+--------------------+
| 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 |
+-----------+---------------------+--------------------+

cu aceste cunoștințe, să vedem cum putem codifica unele caractere în UTF-16. Să alegem un simplu caracter ASCII A (punct de cod: 41chester), un personaj din limba Hindi (indiană), în limba Arabă (pronunțat ca Aa, punct de cod: 9062ster) și un emoticon în limba arabă (numit Happy face, punct de cod: 1F60ACHESTER).

după cum se poate vedea din tabelul de mai sus, atât a, cât și XV pot fi codificate într-o singură unitate de cod a UTF-16, deoarece valorile lor sunt mai mici decât FFFFBH.

când trebuie să codificăm un caracter într-o singură unitate de cod, trebuie doar să convertim punctul de cod al personajului într-un număr binar pe 16 biți. Pentru caracterele a, 00000000 01000001₂ este reprezentarea UTF-16.

în mod similar, pentru caracterul XV, trebuie doar să-i convertim punctul de cod 906bh la un număr binar pe 16 biți, care este 00001001 00000110₂.

în mod normal, reprezentăm unități de cod ale unui caracter în numere hexazecimale. Prin urmare, pentru caracterul a, reprezentarea UTF-16 este 0041bh și, în mod similar, pentru caracter, UTF-16 reprezentarea UTF-16 este 0906bh.

pentru caracterul de la octocus, lucrurile stau un pic diferit. Punctul său de cod este 1F60ACHESTER. Dacă ne uităm la tabelul UTF-16 menționat mai sus, acesta trebuie codificat în 2 unități de cod ale UTF-16. Deci, cum începem?

În primul rând, trebuie să scădem 10000 dB din punctul de cod. Motivul pentru care este, fiecare caracter codificat în 2 unități de cod de UTF-16 a venit după caractere BMP al căror ultimul punct de cod este FFFFBH.

prin urmare, pentru a obține valoarea reală a biților utilizați pentru codificare (care este de 20 în 2 unități de cod), trebuie să scădem 10000ioxidsha din punctul de cod și să folosim numărul final pentru a genera acești 20 de biți.

pentru a vă ajuta să înțelegeți mai bine, primul caracter reprezentat cu 2 unități de cod ale UTF-16 va avea toți cei 20 de biți setați la 0. Deci, valoarea biților folosiți pentru a codifica punctul de cod al acestui caracter este 0. Dar totuși, punctul său de cod este de 10000 dB conform setului de caractere Unicode. Acest lucru se datorează faptului că valoarea obținută de acești 20 de biți este adăugată la 10000ioxidsha pentru a genera punctul final de cod.

după cum am văzut mai devreme, aceste 2 unități de cod arată mai jos.

1101 10xx xxxx xxxx 1101 11xx xxxx xxxx
FIRST CODE UNIT---- SECOND CODE UNIT---

trebuie doar să umplem acești 20 de biți (x) cu valoarea primită de la punctul de cod de caractere. Punctul de cod al caracterului_ixtx este 1f60acd. Dar mai întâi, trebuie să scădem din ea 10000dzhsh. Avem F60ACHESTER.

acum avem nevoie pentru a converti F60AISCO la un număr binar de 20 de biți și umple 20 de biți în șablonul de unitate de cod de mai sus. F60AODAR în binar este 0000111101 1000001010₂. Acum putem umple aceste 20 de biți substituent.

mai jos sunt unitățile finale de cod.

1101 1000 0011 1101 1101 1110 0000 1010
0xD83D 0xDE0A

modalitatea rapidă de a verifica dacă aceste unități de cod sunt valide și, de fapt, dacă aceste perechi surogat pot reprezenta caracterul codificat, deschideți un browser DevTool și introducețiconsole.log('\uD83D\uDE0A'); în consolă.

(Chrome instrumente pentru dezvoltatori)

de asemenea, puteți utiliza acest instrument online pentru a genera puncte de cod UTF-16.

avioane de caractere Unicode

un plan este un grup continuu de 21 de puncte de cod sau 65.536 de puncte de cod. Deoarece UTF-16 a limitat puncte de cod la un maxim de 10ffffbh, avem un total de 17 avioane de caractere în standardul Unicode începând de la 0 la 16.

deoarece 21 de caractere pot fi definite de unitatea unică de cod a UTF-16 (inclusiv punctele de cod surogat), formează primul (0) plan. Acest plan conține aproape toate personajele din limbile de bază din întreaga lume. Acesta este motivul pentru care acest plan este numit Planul Multilingv de bază sau BMP.

în continuare, avem puncte de cod definite de două unități de cod ale UTF-16. Acestea conțin caractere 22⁰, deoarece avem 20 de biți pentru a codifica valoarea punctului de cod. Acestea sunt împărțite în 16 avioane (2 x 21 x). Acestea se numesc avioane suplimentare.

pentru mai multe informații despre aceste planuri, citiți acest document Wikipedia.

comparație cu UCS-2

UCS-2 este o codificare pe 16 biți cu lățime fixă. Aceasta înseamnă că o singură unitate de cod pe 16 biți este utilizată pentru a reprezenta un punct de cod. În teorie, UCS-2 poate reprezenta 21 de caractere distincte, dar există o întorsătură.

btw, folosim termenul unitate de cod în această codificare cu lățime fixă pentru a înțelege relația dintre UTF-16. În realitate, nu există nici un astfel de lucru ca unitate de cod în orice fix cu codificare.

deoarece UCS urmează setul de caractere Unicode, codificarea caracterelor din UCS-2 este identică cu codificarea caracterelor din UTF-16 care sunt reprezentate într-o singură unitate de cod.

Din moment ce UCS urmează setul de caractere Unicode, acesta nu poate codifica un caracter valid cu punctele de cod rezervate surogatelor.

deci, pe scurt, UCS-2 conține caracterele planului Multilingv de bază. Acesta este motivul pentru care unele documente mai vechi și software-ul au folosit codificarea UCS-2. Dar codificarea UCS-2 a devenit învechită și UTF-16 este preferată.

Endianness și BOM

după cum am discutat mai devreme, un document codificat UTF la un nivel scăzut conține secvența de unități de cod. Pentru UTF-8, unitatea de cod are o lungime de 8 biți, în timp ce pentru UTF-16, are o lungime de 16 biți. Aceste unități de cod alcătuiesc caracterele.

un decodor UTF-8 sau UTF-16 citește unitățile de cod secvențial, o unitate de cod la un moment dat pentru a genera caracterele.

fiecare unitate de cod reprezintă o valoare numerică la care un decodor UTF-8 sau UTF-16 poate arunca o privire și poate decide dacă este suficient să reprezinte un caracter sau urmează alte unități de cod care ar trebui luate în considerare și ele.

când vine vorba de UTF-8, lucrurile sunt simple. Deoarece fiecare unitate de cod are o lungime de 8 biți, conversia acelui număr binar pe 8 biți la o valoare numerică este rapidă și ușoară. Acest lucru nu este cazul cu UTF-16, deși.unitatea de cod UTF-16 este un număr binar pe 16 biți (2 octeți) care reprezintă o valoare a punctului de cod. Pentru a genera valoarea numerică din mai mulți octeți, în general, este dificil și diferite sisteme se comportă diferit.

acest comportament depinde de endianitatea sistemului. Din discuția noastră anterioară despre endianitate, există două moduri în care putem scrie o valoare unitară de cod UTF-16. Fie în format big-endian, fie în format Little-endian.

în format Big-endian, MSB este stocat primul și LSB este stocat ultimul. Până în prezent, scriem valoarea unității de cod UTF-16 în format Big-endian. Pentru a scrie valoarea unității de cod UTF-16 în Little-endian, trebuie să schimbăm octeții.

hai sa vorbim despre caracterul inktaktiv. Din exemplul anterior, acesta poate fi reprezentat într-o singură unitate de cod a UTF-16, iar codificarea sa în reprezentare hexazecimală arată ca 0906cd.

0906cd este un număr de 16 biți cu 09 fiind MSB și 06 fiind LSB. Prin urmare, în arhitectura Big-endian, acesta va fi stocat ca 09 06. Cu toate acestea, într-o arhitectură puțin endiană, va fi stocată ca 06 09.

prin urmare, devine responsabilitatea noastră de a codifica caractere luând endianness a sistemului în minte, astfel încât sistemul poate citi un document UTF-16 corect.

dar cum putem spune în prealabil dacă mașina unui utilizator este compatibilă cu documentul codificat sau nu? Și din moment ce endianitatea unui sistem poate afecta modul în care un document este decodificat, cum îl împărtășim public?

Acest lucru este în cazul în care BOM vine în imagine. Un byte Order Mark (BOM) este o secvență de octeți care este adăugată la începutul unui fișier text sau date text.

Unicode recomandă caracterul cu punctul de cod FEFFOCONSTRHSHA să acționeze ca un BOM pentru codificările UTF-16 și UTF-32. Acest caracter ar trebui să fie înainte de primul caracter al documentului. Cu toate acestea, acest caracter nu va fi luat în considerare de decodor în ieșire.

acest caracter (U+FEFF) este un caracter de spațiu fără rupere (ZWNBSP) cu lățime zero și este invizibil. Prin urmare, chiar dacă un decodor nu reușește să recunoască BOM, nu va produce nici o ieșire vizibilă.

acest caracter este reprezentat într-o singură unitate de cod a UTF-16 și în reprezentare hexazecimală arată ca FE (MSB) și FF (LSB).

prin urmare, atunci când caracterele sunt codificate în format big-endian, trebuie să adăugăm FEFF ca BOM la începutul fișierului și când caracterele sunt codificate în format Little-endian, trebuie să adăugăm fffe (invers) ca BOM la începutul fișierului.

Unicode recomandă adăugarea BOM la documentul codificat UTF-16. Cu toate acestea, dacă BOM lipsește, atunci se presupune formatul Big-endian.

IANA preferă UTF-16 ca identificator pentru a semnifica un document codificat UTF-16. Cu toate acestea, UTF-16be este utilizat pentru documentul codificat în format big-endian și UTF-16le este utilizat pentru Format Little-endian.

când se utilizează numele UTF-16BE sau UTF-16le, atunci BOM nu este recomandat să fie prefixat la un fișier. Chiar și în acest caz, dacă se adaugă BOM, atunci acesta va fi considerat caracter ZWNBSP și nu va fi ignorat.

numele UTF-16, UTF-16be și UTF-16le sunt insensibile la majuscule și minuscule.

Pro și contra

UTF-16 este eficient deoarece are doar 2 unități de cod și deoarece cele mai utilizate caractere se încadrează în setul BMP, ele pot fi reprezentate într-o singură unitate de cod. Cu toate acestea, vine cu o mulțime de probleme.

cel mai mare dezavantaj al UTF-16 este că nu este compatibil ASCII. Deoarece caracterele ASCII sunt codificate cu o singură unitate de cod (număr de 16 biți), ele nu pot fi decodate corect de un decodor ASCII.UTF-16 consumă spațiu inutil pentru caracterele ASCII. Comparativ cu documentul codificat UTF-8 care conține doar caractere ASCII, dimensiunea aceluiași document codificat în UTF-16 este de două ori mai mare.

UTF-16 este, de asemenea, afectat de endianitatea sistemului. Dacă BOM lipsește și nu este utilizat un identificator de codificare adecvat (cum ar fi UTF-16le), este posibil ca un document codificat UTF-16 să nu fie decodificat corect.datorită naturii codificării UTF – 16, a introdus puncte de cod surogat care nu pot reprezenta caracterele valide. De asemenea, a limitat setul de caractere Unicode la 10FFFFSCRAFT (ultimul punct de cod).

În ciuda acestor fapte, unele dintre limbajele de programare, cum ar fi JavaScript, Java, etc. și sisteme precum Windows preferă codificarea UTF-16.

Lasă un răspuns

Adresa ta de email nu va fi publicată.