ukotvit menu |
Kódování znaků je trestem programátorů za všechny jejich hříchy a nežádoucí dědictví z dob minulých, kdy se šetřilo každým bitem, které do dnešní doby přežívá díky zkostnatělosti Microsoftu.
O co jde. Počítač je velmi primitivní stroj, který umí přímo pracovat pouze s čísly. To zase nejde moc lidem, ty mají radši písmenka a proto učinili s počítači dohodu. Domluvili se s nimi, že ke každému znaku přiřadí číslo. Počítač tak bude moci pořád pracovat s čísly a lidé přitom budou mít pocit, že pracují se znaky.
Až sem by to bylo v pořádku. Průšvih nastal v tom, že šetřílkové zvolili příliš malý číslený rozsah (1 byte, tedy jen 0 až 255) aby ušetřili paměť a tak bylo znaků mnohem více než čísel (dnes jich je několik desítek tisíc). Problém s nedostatkem čísel se řešil velmi nešťastným způsobem.
Místo aby byl rozšířen číselný rozsah, tak se definovalo několik různých kódovacích sad. V jednu chvíli bylo možno používat jenom jednu kódovou sadu, tedy jen určitý výběr 256 znaků. To bylo sice blbý, ale mnohem horší bylo, že několik různých znaků mělo přiřazeno stejné číslo (kód). Ale protože vždy může být ještě hůř, tak nádavkem toho vznikla různá alternativní kódování. Takže jen pro češtinu existuje neěkolik různých kódování. Standardní iso-8859-2 (používalo se v Linuxu) a nestandardní cp1250 (používá se bohužel dodnes ve windows), cp852 (i toto se bohužel dodnes používá ve windows) a pár dalších, která se už naštěstí nepoužívají.
Aby počítač mohl znak správně zobrazit, musí vědět jakou kódovací sadu (neboli kódování) má použít. A to je informace která se velmi ráda ztrácí, takže se počítač občas zmýlí a zobrazuje různé patvary, protože k číslům přiřazuje nesprávné znaky. Toho jsme občas dodnes svědky.
Lidé pochopitelně časem přišli na to, že mít řadu různých kódování je pěkná kravina, rozšířili číselný rozsah na 4 byte (teoreticky až cca 4 miliardy) a tak vzniklo univerzální kódování, které známe jako Unicode nebo iso-10646-1. V Linuxu je už běžným standardem, Windows je interně taky používají, uživateli ale nutí pořád dvě zastaralá 1 bajtová kódování.
Aby to nebylo tak jednoduché, tak Unicode má sice jednoznačně určeny páry znak-číslo, ale zato to číslo lze napsat různým způsobem. Nejčastěji se používá formát utf-8, a utf-16 a utf-32.
Nejjednodušší formát zápisu. Každý znak může být zapsán jako 4 bytové (32 bitové) číslo. Výhodou je rychlost zpracování, nevýhodou paměťové nároky, protože všechny běžně používané znaky se pohodlně vejdou do dvou bajtů. Proto se moc často nepoužívá, ale u Pythonu je možno při jeho překladu zadat, že má interně používat právě tuto formu.
Tento zápis má dvě formy BE (big endian) a LE (little endian) podle toho jak procesor zapisuje 32 bitová čísla do paměti. Nejčastěhší architektura x86 (Intel, AMD) používá LE.
Formát utf-32 a ucs4 jsou různé názvy pro to samé, není mezi nimi významný rozdíl.
Nejpoužívanější formát zápisu v textových dokumentech, jako je např HTML nebo různé XML. V Linuxu je to u desktopových distribucí výchozí kódování. Tento formát má řadu výhod. Ćísla se nezapisují jako 32 bitové číslo, ale jako nejmenší možná sekvence bajtů. Pořadí bajtů se proto nemění, tudíž u utf-8 se neprojevuje BE a LE, je pořád stejné.
Nejčastěji používané znaky (ASCII) se zapisují pomocí jednoho bajtu. ASCII je tedy kompatibilní s utf-8. Na největší čísla je sice potřeba až 5 bajtů, ale protože ty jsou přiřazena ke vzácným znakům, vychází utf-8 statisticky jako nejúspornější formát.
Další obrovskou výhodou bajtové sekvence je její kompatibilita s jazyky C a C++ (v nich je naprogramováno nejvíce software na světě), které k označení konce řetězce (textu v paměti počítače) používají speciální znak/byte s kódem 0. Utf-8 je jediný formát Unicode, který toto umožňuje používat, v ostatních Unicode formátů se jako součást znaku může objevit byte s hodnotou 0 i uprostřed řetězce.
Problémem tohoto formátu je, že různé znaky jsou jinak velké (zabírají různý počet bajtů), což trochu zpomaluje zpracování takového textu. Proto některé programy interně používají vnitřně rychlé ucs2 nebo ucs4, a utf-8 používají jen na vstupu a výstupu (provádí překódování).
Formát ucs2 je stejný jako ucs4 nebo utf-32, pouze místo 4 bajtů používá 2 bajty. Neumí tedy Unicode používat v plném rozsahu, ale v praxi to příliš nevadí. Tento formát používá defaultně Python pro vnitřní zpracování Unicode.
Formát utf-16 je hybrid mezi ucs4 a utf-8, je to asi nejhorší možné řešení. Podobně jako ucs2 používá 2 bajty, ale nedostatečný rozsah řeší skládáním dvoubajtů podobně jako to dělá utf-8 skládáním bajtů. Z obou si to tedy bere to nejhorší. Na rozdíl od utf-8 není kompatibilní s C ani ASCII a ani nemá rychlé zpracování jako usc2 nebo ucs4.
Toto nejhorší řešení používá Microsoft u Windows. Pravděpodobně původně používal formát ucs2, ale když mu začal vadit jeho omezený rozsah, přistoupil k používání utf-16 jako snazšímu řešení (obojí je dvoubajtové), než Windows přeprogramovat na používání ucs4.
Protože Microsoft udržuje při životě stará jednobajtová kódování, máme dodnes problémy při zpracování textů. Programátor na to musí neustále myslet. V jakém kódování jsem obdržel data, v jakém kódování je mám poslat dál, v jakém je mám uložit a v jakém je mám zobrazit na obrazovce?
Program napsaný v Pythonu, který v Linuxu krásně funguje, protože se v něm používá jednotně univerální kódování může mít ve Windows problémy. A pravděpodobně bude, pokud na to programátor nemyslí.
Klidně se ve Windows může stát, že obdržíme data z klávesnice v cp1250, na konzoli je budeme muset zobrazit v cp852 a do souboru nebo databáze je můžeme chtít uložit nebo na web poslat v univerzálním utf-8. V linuxu se přitom vždy použije jen ono utf-8.
Naštěstí má Python práci s kódováním docela propracovanou, přesto (nebo možná právě proto) se zde mohou skrývat záludnosti.