Aplikační a programové vybavení Krátká přednáška na téma znakových sad a jejich použití v aplikacích. Znakové sady
Základní pojmy Znak – symbol Kódování ≈ znaková sada = kódová stránka (encoding ≈ character set (charset) = code page) Je systém přiřazování číselných kódů znakům. Je reprezentováno tabulkou (mapování). Cílem je možnost ukládat symboly ve formě čísel. Kódové slovo – kód přiřazený symbolu Kódová jednotka – elementární část kódu Rozdíl mezi kódováním a znakovou sadou bude vysvětlen na následujících slajdech. Existence znakové sady je nezbytná proto, aby bylo možné jednotlivé symboly reprezentovat čísly, tato čísla převést na binární čísla a tyto ukládat jako posloupnost 0 a 1 do nějaké paměti.
Jedno-bytové kódování Délka kódu je maximálně jeden byte (single-byte) Znaková sada ASCII (základní) délka kódu: 7 bitů → 128 znaků Obsahuje znaky anglické abecedy, čísla, základní interpunkční znaménka a řídící (netisknutelné) znaky (control characters) NULL, CR, LF, TAB, ... „Rozšířená sada ASCII“ = „Národní znakové sady“ délka kódu: 8 bitů → 256 znaků Různé varianty obsahují různé specifické národní znaky. Výhodou je snadné zpracování a rychlost. Nevýhodou je nedostatečný rozsah sady (čínština má tisíce znaků). Dnes se obvykle pojmem „kódování ASCII“ označuje některá z rozšířených sad ASCII. Problém těchto znakových sad je jednak v tom, že se do nich nevejdou všechny znaky a druhotně v tom, že některé znaky mají přiřazeny stejné kódy. Tj. při čtení dat z paměti je jasné, že kód 65 je znak A, protože tak je to v základní ASCII sadě. Není už ale jasné, jak se má vykreslit kód 153, který někde představuje znak ™ a jinde znak ř. K datům je tedy nutné nést dodatečnou informaci o jejich kódování.
Tabulka znakové sady Win-1250
Více-bytové kódování Délka kódu je jeden a více bajtů (multi-byte) Kódovou jednotkou je jeden byte. Rozsah znakové sady závisí na počtu kódových jednotek. Dvě základní varianty: Všechny znaky jsou kódované stejným počtem bytů. Každý znak může být kódován různým počtem bytů podle potřeby (operace s řetězci jsou náročnější). Pokud použijeme jeden byte, máme možnost uložit 28 = 256 znaků. Pokud použijeme dva bajty, máme možnost uložit 216 = 65 536 znaků.
Národní znakové sady Základní znaková sada ASCII obsahuje pouze znaky anglické abecedy – jedno-bytové kódování. Neobsahuje žádné znaky národních abeced. V 80. letech vzniklo množství národních znakových sad. Pro češtinu existují: ISO-8859-2 (ISO Latin 2) windows-1250 (CP1250) CP852 (PC Latin 2) a další: KEYBCS2 (kódování bratrů Kamenických, CP859), East8, ICL, Cork Klíčovým problémem je nedostatek pozic pro různé národních znaky – jednotlivé znaky se překrývají. Překrývání pozic vede pochopitelně k nejednoznačnosti a tedy k neustálým problémům s kódováním.
Unicode Současně se vznikem národních kódování začala vznikat univerzální znaková sada – více-bytové kódování. Dvě iniciativy – Unicode Consortium a ISO. V roce 1991 se již dříve kompatibilní standardy sloučily do Unicode. Všechny verze standardu Unicode vychází souběžně jako ISO standardy. Jednotlivé verze standardu jsou vzájemně kompatibilní. Poslední verze Unicode 7.0 vyšla v roce 2014 http://www.unicode.org Řešením je použití univerzální znakové sady Unicode. Možná se vtírá otázka, proč vznikly národní znakové sady, když současně vznikala sada univerzální. Odpověď je, že národní znakové sady byly v podstatě provizorní řešení, které se mělo používat pouze dočasně, než dojde ke standardizaci a implementaci Unicode (což bohužel zabralo skoro 20 let).
Unicode Znaková sada Unicode definuje několik kódování: UTF-7, UTF-8, UTF-16 a UTF-32. Kromě kódování Unicode (UTF-n) se používají ještě starší kódování ISO: UCS-2, UCS-4. Velikost kódové jednotky je 1, 2 nebo 4 byty. Pokud je kódová jednotka větší jak 1 byte, tak je nutné určit pořadí bytů. Big Endian (výchozí) nebo Little Endian (běžnější) Pořadí bytů se určuje značkou BOM (Byte Order Mark) na začátku souboru/dat. Zde je možné vrátit se k otázce z prvního slajdu – rozdíl mezi znakovou sadou a kódováním. Znaková sada je tabulka, která jednotlivým znakům přiřazuje čísla. Její standardizace je zcela klíčová, protože jedině takto se odstraní nejednoznačnost. V Unicode existuje pouze jediná znaková sada a je tedy vždy jasné, že kód 159 je malé ř. Současně však Unicode definuje několik kódování – tedy způsobů jak tento kód fyzicky reprezentovat v paměti. Pokud je to v jednom bytu, bude 153 zapsáno jako 10011001. Pokud bude znak uložený ve dvou bytech, může to být třeba 10011001 00000000 (Big Endian) nebo: 00000000 10011001 (Little Endian) Důvody pro existenci Little a Big endian pořadí jsou hardwarové (viz http://en.wikipedia.org/wiki/Endianness) a není nutné se jimi teď zabývat. Důležité je, že LE a BE současně s tím, že je hodnotu možné uložit do jednoho a více bajtů vede k celé řadě možných reprezentací kódu znaku v paměti a tedy k celé řadě Unicode kódování.
Unicode kódování UTF-8 UTF-16 UTF-32 UCS-2 UCS-4 Min. počet bytů 1 2 4 Max. počet bytů Velikost kódové jednotky 8 bitů 16 bitů 32 bitů Unicode nevyužívá úplně všechny kombinace 0 a 1, které lze zapsat do 32 bitů. Pokud je například velikost kódové jednotky 8 bitů, používají se některé rozsahy k identifikaci Unicode má nyní 113,021 znaků. Více jak 800000 dalších pozic je volných. Kromě toho umožňuje i definice vlastních znaků.
Unicode kódování – srovnání UTF-8 UTF-16 UTF-32 UCS-2 UCS-4 Všechny znaky ano ne Proměnná délka znaku Režie malá střední velká Kompatibilní s ASCII Závisí na pořadí bytů Doporučeno k používání Režie kódování jsou „vyplýtvané“ bajty. Například pokud je nutné uložit znak s kódem 153, stačí k tomu jeden bajt. V kódování UTF-32 budou ale použity 4 bajty (protože velikost kódové jednotky jsou 4 bajty). Pro běžné aplikace je nejvýhodnější kódování UTF-8, jednak je velmi kompatibilní a nevyžaduje laborování s pořadím bytů. V databázových systémech se pro změnu používá kódování UTF-32 a to z toho důvodu, že pevná délka jednoho znaku v bajtech umožňuje implementaci rychlejších algoritmů vyhledávání. Daní za to je ovšem (až čtyřnásobně) větší spotřeba místa na disku.
function utf8_strlen($str) { $count = 0; for ($i = 0; $i < strlen($str); $i++) { //pres vsechny znaky $value = ord($str[$i]); if ($value > 127) { if ($value >= 192 && $value <= 223) { $i++; } elseif ($value >= 224 && $value <= 239) { $i = $i + 2; } elseif($value >= 240 && $value <= 247) { $i = $i + 3; } else { echo ‘Not a UTF-8 compatible string ' } } $count++; return $count; Příklad funkce, která zjistí o jakou délku znaku se jedná v UTF-8 řetězci. Pokud je hodnota prvního znaku větší jak 127 jedná se o více bajtový znak. Z toho také plyne, proč UTF-8 (a Unicode celkově) nevyužívá všechny možné kombinace 0 a 1 v daném rozsahu bytů. Tato funkce slouží pouze k demonstraci principu, není ani efektivní ani dokonalá. Pokud budete však něco podobného potřebovat ve své aplikaci, použijte standardní funkci mb_strlen().
Unicode – shrnutí UTF-8 řeší naprostou většinu všech problémů s kódováním. Aplikace může pracovat s daty v libovolném jazyce. Podpora ze strany aplikací je stále ještě špatná. Pro reprezentaci dat uvnitř aplikace může být někdy výhodnější využít kódování s konstantním počtem bytů na jeden znak. Příliš žluťoučký kůň pěl ďábelské ódy. Stále bohužel platí, že podpora Unicode je na mnoha místech špatná. Je to způsobenou celou řadou faktorů. Například tím, že je složitější podporovat více kódování, nebo tím, že nejběžnější kódování UTF-8 má proměnnou délku znaku, což komplikuje vytváření pod-řetězců a porovnávání řetězců. Například PHP interně stále používá jednobajtové řetězce a pro práci s více bajtovým kódováním je nutné použít speciální funkce mb_XXX().
http://kantorek.webzdarma.cz/
Otázky? Definuje UTF-8 znaky nebo obrázky? Jaký je v tom rozdíl? Obsahuje UTF-8 znaky Klingonštiny? Jaký je rozdíl mezi kódováním a znakovou sadou? Je možné převádět data mezi UTF-8 a UTF-32? Hrozí přitom záměna znaků? Kdy je dobré použít jedno-bytové kódování? Má nějaký smysl používat kódování UTF-16? Kolik netisknutelných znaků lze „napsat“ na klávesnici?