Text: od ASCII k UTF-8
Písmeno není v paměti. V paměti je číslo, a někde je dohoda, které číslo znamená které písmeno. ASCII z roku 1963 má 128 znaků a vejde se do sedmi bitů — což stačilo pro angličtinu a pro nic jiného.
Osmý bit pak každý použil po svém: Latin-2, Windows-1250, KOI8, CP852 a další. Všechny se shodovaly na prvních 128 znacích a rozcházely na zbytku, takže české „ř“ bylo v každé jiné číslo. Odtud pochází „rozsypaný čaj“ — text se vykreslil podle jiné tabulky, než ve které vznikl.
Unicode odděluje dvě otázky, které se do té doby pletly
- Které číslo patří kterému znaku? To je Unicode. „ř“ je U+0159, a bude jím navždycky. Čísel je přes milion (U+0000 až U+10FFFF).
- Jak se to číslo uloží do bajtů? To je kódování — UTF-8, UTF-16, UTF-32 — a je jich víc, protože každé řeší jiný kompromis.
UTF-8 a proč vyhrálo
| rozsah | bajtů | tvar |
|---|---|---|
| U+0000 – U+007F | 1 | 0xxxxxxx |
| U+0080 – U+07FF | 2 | 110xxxxx 10xxxxxx |
| U+0800 – U+FFFF | 3 | 1110xxxx 10xxxxxx 10xxxxxx |
| U+10000 – U+10FFFF | 4 | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
Tři vlastnosti, kvůli kterým to vyhrálo:
- ASCII je podmnožina. Anglický text je bajt po bajtu totožný s tím, co byl předtím. Žádná konverze, žádná migrace.
- Pokračovací bajt je poznat. Začíná vždycky
10, takže se dá skočit doprostřed souboru a najít hranici znaku couvnutím o pár bajtů. To u jiných kódování nejde. - Nikde není nula. Žádný bajt uvnitř vícebajtového znaku není 0x00, takže céčkové řetězce zakončené nulou fungují dál.
Praktický důsledek pro češtinu: každé písmeno s diakritikou
zabere dva bajty. Český text je tedy v UTF-8 asi o 5–10 % delší než anglický téže
délky, a strlen() nad ním nevrací počet písmen. „Délka řetězce“ má nejmíň tři různé
odpovědi — počet bajtů, počet kódů znaků a počet toho, co uživatel považuje za písmeno.
UTF-16 a ta věc s délkou dvě
UTF-16 ukládá většinu znaků do dvou bajtů, ale na ty nad U+FFFF nestačí — pro ně používá náhradní pár, dvě šestnáctibitová čísla z vyhrazeného rozsahu D800–DFFF. Tyhle poloviny nejsou znaky; existují jen jako útěková cesta a v UTF-8 nemají zápis.
Řetězec v JavaScriptu, v Javě i ve Windows API je UTF-16. Proto:
To není chyba jazyka. Je to ta samá věc, jen viditelná: „délka“ znamená počet uložených jednotek, ne počet písmen.