Úvod do kódování znaků

UTF-16

UTF-16 je schéma kódování s proměnnou délkou 16 bitů a používá znakovou sadu UTF pro Kódové body znaků. To znamená, že kódovaný znak UTF-16 bude mít 16bitovou kódovou jednotku.

Jak víme, že kódování UTF-8 znak může být reprezentován v 1 až 4 kód jednotky, UTF-16 znak může být reprezentován v 1 nebo 2 jednotek kódu. Znak UTF-16 tedy může mít 16 nebo 32 bitů paměti na základě svého kódového bodu.

před skokem do specifikací kódování UTF-16 pochopíme, jak můžeme UTF-16 fungovat.

protože máme 16bitovou kódovou jednotku, teoreticky můžeme kódovat 21⁶ znaků z kódového bodu 0 do 65 535. Ale co když máme znak s kódovým bodem větším než 65 535? V tom případě můžeme přidat další kódovou jednotku.

S extra kód jednotky, můžeme kódovat celkem 232 znaků, což je více než 4M. Potom je ale otázka, jak UTF-16 dekodér bude vědět, že je třeba zvážit 2 kód jednotky dekódovat znak?

UTF-8 vyřešil tento problém tím, že nastavení počáteční bity prvního kód jednotky a pokračování kód jednotky k nějaké konkrétní hodnoty, které UTF-8 dekodér lze použít na odpočet, kolik jednotek kódu postava může mít.

můžeme udělat totéž s kódovou jednotkou UTF-16, ale pak musíme obětovat některé bity v kódové jednotce pro tuto funkci. Můžeme nastavit některé počáteční bity kódové jednotky na nějakou smysluplnou hodnotu, které dekodér UTF-16 rozumí.

Také, aby self-synchronizace napájení jednotek kódu, kód jednotky musí být schopen říci, zda je počáteční kód jednotky nebo pokračování kód jednotky a není postava jen jednoho kódu jednotky.

Unicode rozhodl obětovat původní 6 bitů kódu jednotky zůstalo pouze 10 bitů pro zakódování bod kódu znaku na kód jednotky. Pokud znak potřebuje 2 kódové jednotky, 20 bitů paměti (z 32 bitů nebo 4 bajtů) obsahuje aktuální informace o kódovém bodu znaku.

jaké jsou tedy tyto počáteční bity a jak tyto bity vytvářejí důlek v znakové sadě UTF? Podívejme se na níže uvedený příklad.

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

ze standardu UTF-16 by první kódová jednotka měla začínat 110110₂ a druhá kódová jednotka by měla začínat 110111₂. To pomůže dekodéru UTF-16 pochopit, který z nich je první kódová jednotka a který z nich je druhý. Díky tomu se UTF-16 synchronizuje.

nyní, co máme 10 bitů na kódovou jednotku na hraní, jaký je rozsah, ve kterém můžeme hrát? Nakonec, kolik znaků lze zakódovat ve dvou kódových jednotkách kódování UTF-16?

nebojte se, budeme mluvit o znacích zakódovaných pouze v jedné kódové jednotce.

Pokud se podíváte na výše uvedený kód jednotky šablony, máme nabídku od 1101 1000 0000 0000₂ na 1101 1111 1111 1111₂. To odpovídá D800₁₆ Dfff₁₆.

first první kódová jednotka má rozsah od D800 to do 6fff₁₆ a druhá kódová jednotka má rozsah od dc00 to do DFFF₁₆. Tyto hodnoty můžeme získat otočením všech bitů kódových bodů: zapnutí a vypnutí.

Od UTF-16 musí být self-synchronizace, body kódu mezi D800₁₆ a DFFF₁₆ nesmí představovat znak v UTF-16. Protože všechna kódování UTF sledují stejnou znakovou sadu UTF, jsou tyto Kódové body omezeny UTF a nejsou a nebudou přiřazeny žádným znakům⁰.

Kódové body mezi D800₁₆ a dfff₁₆ nepředstavují žádné znaky, proto se nazývají náhradní Kódové body nebo společně se také nazývají náhradní páry⁰.

první náhradní kódový bod (z první kódové jednotky) se také nazývá jako vysoký náhradní a druhý kódový bod (z druhé kódové jednotky) se také nazývá nízký náhradní. Takže celkem 2048 kódových bodů, 1024 na náhradníka.

sur náhradní Kódové body obětovaly svůj život, abychom mohli kódovat více znaků dvěma kódovými jednotkami. Přemýšlej o tom!

takže velká otázka, můžeme kódovat znak s jednou kódovou jednotkou UTF-16? Odpověď zní ano. UTF-16 je 16bitové schéma kódování s proměnnou délkou. Znamená to tedy, že můžeme kódovat 21⁶ znaků jednou kódovou jednotkou?

odpověď zní ne. Teoreticky bychom mohli zakódovat 21⁶ znaky s kódem bod 0000₁₆ (0₁₀) FFFF₁₆ (65535₁₀), ale body kódu mezi D800₁₆ a DFFF₁₆ nepředstavují žádné znaky, jako jsou vyhrazena.

Proto to je bezpečné kódovat znaky z 0000₁₆ na D7FF₁₆ a E000₁₆ na FFFF₁₆ který opouští účty 63,488 (65536-2048) znaky. To je jen pro znaky, které mohou být zakódovány pouze v jedné kódové jednotce UTF-16.

když máme celkem 20 bity hrát s, pokud jde o znaky, než mohou být kódovány ve 2 jednotek kódu UTF-16, můžeme kódovat 22⁰ více znaků, což je 1 048 576 znaků.

Takže celkem můžeme kódovat 1,048,576 + 63,488 která činí 1,112,064 znaky (více než 1 milion znaků). Toto je limit znakové sady UTF. Protože UTF-16 může kódovat tyto mnoho znaků, jiné kódování UTF nemohou reprezentovat znaky mimo tyto znaky.

UTF charset Code Points

protože víme, že kódový bod je desetinná hodnota přiřazená znaku, nesmíme (Unicode) přiřadit neplatný kódový bod skutečnému znaku. Dosud jsou neplatné Kódové body náhradními kódovými body.

S jen jeden UTF-16 kód jednotky, můžeme kódovat 63,488 postav v rozmezí od 0000₁₆ na D7FF₁₆ a E000₁₆ na FFFF₁₆. Poslední kódový bod je 65 535. Ty se nazývají BMP znaky (vysvětleno později).

S dvou jednotek kódu UTF-16, můžeme kódovat 1,048,576 znaky. Vzhledem k tomu, že nemůžeme znovu začít od hodnoty 0 (kódový bod), protože tyto přicházejí po BMP znaků, musíme je kompenzovat 65,536. Tyto znaky se nazývají doplňkové znaky (vysvětleny později).

proto má první doplňkový znak hodnotu kódového bodu 65536₁₀, což odpovídá 10000₁₆. Od té doby můžeme kódovat 1,048,576 znaky s dvou jednotek kódu UTF-16, poslední bod kódu je 1114111₁₀ což je ekvivalentní 10FFFF₁₆.

pojďme tedy rozebrat věci jednoduchou tabulkovou formou.

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

s těmito znalostmi uvidíme, jak můžeme kódovat některé znaky v UTF-16. Vybereme jednoduchý ASCII znak (kód bodu: 41₁₆), postava z Hindština (Indie) jazyk आ (vyslovováno jako Aa, kód bodu: 906₁₆) a emotikon 😊 (nazýván jako Šťastný obličej, kód bodu: 1F60A₁₆).

jak vidíme z výše uvedené tabulky, A i आ mohou být zakódovány pouze v jedné kódové jednotce UTF-16, protože jejich hodnoty jsou menší než FFFF₁₆.

když musíme kódovat znak pouze v jedné kódové jednotce, musíme převést kódový bod znaku na 16bitové binární číslo. Pro znaky a, 00000000 01000001₂ je reprezentace UTF-16.

podobně pro znak आ stačí převést jeho kódový bod 906₁₆ na 16bitové binární číslo, které je 00001001 00000110₂.

normálně reprezentujeme kódové jednotky znaku v hexadecimálních číslech. Proto pro znak a je reprezentace UTF-16 0041₁₆ a podobně pro znak je reprezentace UTF-16 आ 0906₁₆.

pro znak 😊 jsou věci trochu jiné. Jeho kódový bod je 1F60A₁₆. Pokud se podíváme na výše uvedenou tabulku UTF-16, musí být zakódována ve 2 kódových jednotkách UTF-16. Tak jak začneme?

nejprve musíme odečíst 10000₁₆ od kódového bodu. Důvodem je, že každý znak zakódovaný ve 2 kódových jednotkách UTF-16 přišel po znacích BMP, jejichž posledním kódovým bodem je FFFF₁₆.

Proto, aby se skutečná hodnota bitů použitých pro kódování (což je 20 v 2 kód jednotky), musíme odečíst 10000₁₆ od bod kódu a používat konečné číslo pro generování těchto 20 bitů.

💡, Aby vám pomohl lépe pochopit, první znak reprezentován s 2 jednotek kódu UTF-16 bude mít všechny své 20 bity nastaveny na 0. Hodnota bitů použitých pro kódování kódového bodu tohoto znaku je tedy 0. Jeho kódový bod je však 10000₁₆ podle znakové sady Unicode. Je to proto, že hodnota získaná těmito 20 bity se přidá k 10000₁₆, aby se vygeneroval konečný kódový bod.

Jak je vidět dříve, tyto 2 kódové jednotky vypadají níže.

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

stačí vyplnit těchto 20 bitů (x) hodnotou přijatou z bodu kódu znaků. Kódový bod znaku 😊je 1F60A₁₆. Nejprve však musíme od něj odečíst 10000₁₆. Dostaneme F60A₁₆.

nyní musíme převést F60A₁₆ na 20bitové binární číslo a vyplnit 20 bitů ve výše uvedené šabloně kódové jednotky. F60A₁₆ v binárním jazyce je 0000111101 1000001010₂. Nyní můžeme vyplnit těchto 20 zástupných bitů.

níže jsou uvedeny konečné kódové jednotky.

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

rychlý způsob, jak zkontrolovat, pokud se těchto jednotek kódu jsou platné, a ve skutečnosti, pokud tyto náhradní dvojice může reprezentovat kódováním znaků, otevřete Prohlížeč DevTool a zadejte console.log('\uD83D\uDE0A'); v konzoli.

(Chrome Developer Tools)

můžete také použít tento on-line nástroj pro generování UTF-16 kód body.

znakové roviny Unicode

rovina je spojitá skupina 21⁶ nebo 65 536 kódových bodů. Protože UTF-16 má omezené Kódové body na maximálně 10FFFF, máme ve standardu Unicode celkem 17 znaků od 0 do 16.

protože 21 znaků může být definováno jednotkou kódu UTF-16 (včetně náhradních kódových bodů), tvoří první (0.) rovinu. Tato rovina obsahuje téměř všechny znaky v základních jazycích po celém světě. Proto se tato rovina nazývá základní Vícejazyčná rovina nebo BMP.

dále máme Kódové body definované dvěma kódovými jednotkami UTF-16. Ty obsahují 22⁰ znaků, protože máme 20 bitů pro kódování hodnoty kódového bodu. Ty jsou rozděleny do 16 rovin (2⁴ x 21⁶). Nazývají se doplňkové roviny.

💡 Další informace o těchto rovinách naleznete v tomto dokumentu Wikipedie.

porovnání s UCS-2

UCS-2 je 16bitové kódování s pevnou šířkou. To znamená, že pouze jedna 16bitová kódová jednotka se používá k reprezentaci kódového bodu. Teoreticky může UCS-2 představovat 21 odlišných znaků, ale je tu zvrat.

💡 BTW, používáme termín kód jednotky v tomto pevné-šířka kódování porozumět vztahu mezi UTF-16. Ve skutečnosti neexistuje žádná taková věc jako kódová jednotka v žádném pevném kódování.

Vzhledem k tomu, UCS následuje Unicode znakové sady, kódování znaků v kódování UCS-2 je shodný s kódování znaků v UTF-16, které jsou zastoupeny v jen jeden kód jednotky.

💡 Od UCS navazuje na znaková sada Unicode, to nemůže kódovat platný znak s kódem bodů vyhrazena pro náhradníky.

takže ve zkratce, UCS-2 obsahuje znaky základní Vícejazyčné roviny. To je důvod, některé starší dokumenty, a software používá kódování UCS-2. Kódování UCS-2 se však stalo zastaralým a preferuje se UTF-16.

Endianness a BOM

jak jsme diskutovali dříve, UTF kódované dokumenty na nízké úrovni obsahují posloupnost kódových jednotek. Pro UTF-8 je kódová jednotka dlouhá 8 bitů, zatímco pro UTF-16 je dlouhá 16 bitů. Tyto kódové jednotky tvoří znaky.

dekodér UTF-8 nebo UTF-16 čte kódové jednotky postupně, jednu kódovou jednotku najednou pro generování znaků.

Každý kód jednotka představuje číselnou hodnotu, která UTF-8 nebo UTF-16 dekodér může podívat a rozhodnout, zda je dostatečně reprezentovat charakter, nebo je následuje další kód jednotky, které by měly být považovány za stejně.

Pokud jde o UTF-8, věci jsou jednoduché. Protože každá kódová jednotka je 8 bitů dlouhá, převod tohoto 8bitového binárního čísla na číselnou hodnotu je rychlý a snadný. To však není případ UTF-16.

kódová jednotka UTF-16 je 16bitové (2 bajtové) binární číslo, které představuje hodnotu kódového bodu. Generovat číselnou hodnotu z více bajtů je obecně složité a různé systémy se chovají odlišně.

toto chování závisí na endianitě systému. Z naší dřívější diskuse o endianitě existují dva způsoby, jak můžeme napsat jednotkovou hodnotu kódu UTF-16. Buď ve formátu Big-endian nebo Little-endian formátu.

ve formátu Big-endian je MSB uložen jako první a LSB je uložen jako poslední. Zatím píšeme jednotkovou hodnotu kódu UTF-16 ve formátu Big-endian. Chcete-li zapsat jednotkovou hodnotu kódu UTF-16 V Little-endian, musíme vyměnit bajty.

promluvme si o znaku आ. Z dřívějšího příkladu může být reprezentován pouze v jedné kódové jednotce UTF-16 a jeho kódování v hexadecimální reprezentaci vypadá jako 0906₁₆.

0906₁₆ je 16bitové číslo, přičemž 09 je MSB a 06 je LSB. Proto v Big-endian architektury, bude uložen jako 09 06. V trochu endovské architektuře však bude uložen jako 06 09.

proto je naší odpovědností zakódovat znaky tím, že vezmeme v úvahu endiannost systému, aby systém mohl správně číst dokument UTF-16.

ale jak můžeme předem zjistit, zda je počítač uživatele kompatibilní s kódovaným dokumentem nebo ne? A protože endianita systému může ovlivnit způsob dekódování dokumentu, jak jej sdílíme veřejně?

to je místo, kde BOM přichází do obrázku. Značka Byte Order (BOM) je posloupnost bajtů, která je přidána na začátek textového souboru nebo textových dat.

Unicode doporučuje, aby znak s kódovým bodem FEFF₁₆ fungoval jako kusovník pro kódování UTF-16 a UTF-32. Tento znak by měl být před prvním znakem dokumentu. Tento znak však dekodér ve výstupu nezohlední.

tento znak (u+FEFF) je znak bez přerušení (ZWNBSP) s nulovou šířkou a je neviditelný. Proto i když dekodér nerozpozná kusovník, nebude produkovat žádný viditelný výstup.

tento znak je reprezentován v jedné kódové jednotce UTF-16 a v hexadecimální reprezentaci vypadá jako FE (MSB) a FF (LSB).

Proto, když znaky jsou kódovány v Big-endian formát, musíme přidat FEFF jako BOM na začátku souboru a když znaky jsou kódovány v Little-endian formát, musíme přidat FFFE (reverzní) jako BOM na začátku souboru.

Unicode doporučuje přidat kusovník do dokumentu kódovaného UTF-16. Pokud však BOM chybí, předpokládá se Formát Big-endian.

IANA preferuje UTF-16 jako identifikátor pro označení dokumentu kódovaného UTF-16. UTF-16BE se však používá pro dokument kódovaný ve formátu Big-endian a UTF-16LE se používá pro formát Little-endian.

je-li použit název UTF-16BE nebo UTF-16LE, pak se nedoporučuje předdefinovat kusovník do souboru. I v tomto případě, pokud je kusovník přidán, bude považován za znak ZWNBSP a nebude ignorován.

names názvy UTF-16, UTF-16BE a UTF-16LE jsou malá a velká písmena.

Klady a Zápory

UTF-16 je efektivní, protože to má pouze 2 kód jednotky, a protože většina používaných znaků podzim v BMP nastavit, mohou být zastoupeny jen jednoho kódu jednotky. Přichází však se spoustou problémů.

největší nevýhodou UTF-16 je, že není kompatibilní s ASCII. Protože znaky ASCII jsou kódovány jednou kódovou jednotkou (16bitové číslo), nemohou být dekodérem ASCII správně dekódovány.

UTF-16 spotřebovává zbytečné místo pro znaky ASCII. Ve srovnání s dokumentem zakódovaným UTF-8, který obsahuje pouze znaky ASCII, je velikost stejného dokumentu zakódovaného v UTF-16 dvakrát větší.

UTF-16 je také ovlivněn endianitou systému. Pokud kusovník chybí a není použit vhodný identifikátor kódování (jako UTF-16LE), kódovaný dokument UTF-16 nemusí být správně dekódován.

vzhledem k povaze kódování UTF-16 zavedla náhradní Kódové body, které nemohou reprezentovat platné znaky. Také omezil znakovou sadu Unicode na 10FFFF (poslední kódový bod).

navzdory těmto skutečnostem, některé z programovacích jazyků, jako je JavaScript, Java, atd. a systémy jako Windows preferují kódování UTF-16.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.