Práce s UTF-8
Školení, která pořádám
Kódování UTF-8 se od většiny ostatních kódování liší tím, že znaky ukládá do proměnlivého počtu bajtů – spodní polovinu ASCII tabulky do jednoho bajtu, např. česká písmena s diakritikou do dvou bajtů a např. čínské znaky do tří nebo čtyř bajtů. Kvůli tomu pochopitelně nefungují běžné funkce, které pracují s pozicí v řetězci (např. substr) ani je nelze snadno upravit jako např. v případě dvoubajtového kódování UCS-2. Náhradu pro základní funkce poskytuje knihovna iconv (např. iconv_substr), která je v PHP 5 k dispozici už v základní výbavě. Pokročilejší funkce nabízí knihovna MBString, navíc s možností namapovat je direktivou mbstring.func_overload na běžné funkce.
<?php
iconv_set_encoding("internal_encoding", "UTF-8");
if (iconv_strlen($_POST["jmeno"]) < 3) {
echo "Jméno musí mít alespoň tři znaky.\n";
}
?>
Pro převod kódování se dají použít obě, rozšíření Recode se naopak doporučuji vyhnout, protože za převedené řetězce za určitých okolností přidává nesmyslné znaky.
Podporu kódování UTF-8 mají i Perlovské funkce pro práci s regulárními výrazy, stačí použít modifikátor u
. Regulární výrazy potom budou pracovat místo s bajty se znaky v kódování UTF-8.
<?php
if (!preg_match('~.{3,} [0-9]+~u', $_POST["adresa"])) {
echo "Adresa musí mít alespoň tři znaky a číslo domu.\n";
}
?>
Při vytváření skriptů je potřeba dávat pozor ještě na jednu věc – některé editory uvozují soubor v kódování UTF-8 posloupností bajtů, která vyznačuje pořadí bajtů v Unicode souborech. Pro PHP interpret to je ale výstup jako každý jiný, takže u takto uvozených dokumentů nelze používat např. funkci header nebo setcookie. Obejít se to dá zapnutím direktivy output_buffering, vyřešit potom vytvářením souborů bez těchto prvotních znaků (např. ve SciTE tomu odpovídá kódování UTF-8 Cookie
).
Diskuse
Obzvláště je vhodné si na té stránce přečíst update, protože informace o endianech jsou v zásadě správně, ale spojení s UTF-8 je zcela mylné.
Lukoko:
Jen doplním, že sekvenci bytu na začátku UTF-8 dokumentu se říká BOM.
"Náhradu pro základní funkce poskytuje knihovna iconv (např. iconv_substr), která je v PHP 5 k dispozici už v základní výbavě" - toto platí samozřejmě jen po Windows, nad Linuxem je potřeba ji manuálně stáýhnout a zkompilovat, není součástí zdrojáků PHP 5
UTF-8 BOM by snad melo resit --enable-zend-multibyte pri ./configure, ale popravde, jeste jsem se nedostal k overeni/vyvraceni.
Garf:
Mám k UTF-8 jeden dotaz: jak lze rozumně upravovat stránky/skripty pokud jsou napsané v kódování UTF-8? Kromě editoru, kde můžu zvolit znakovou sadu souboru i v jakém formátu se děje úprava, jsem zatím narazil vždy na problém, že otevřu-li skript/stránku napsanou v UTF-8 např. v notepadu, pak vidím jen rozsypaný čaj, protože notepad používá znakvou sadu windows, tedy 1250. Jak to lze obejít? Pokud nějak? Asi neexistuje něco takového, jako UTF-8 jako "systémová sada"... (pokud je to hloupý dotaz, omlouvám se - nedávno jsem na ten problém narazil, když jsem se rozhodl předělat vše na UTF-8, a nepodařilo se mi jej vyřešit)
Štěpán Svoboda:
Ahoj Jakube,
teď jsem narazil na zajímavý problém. Nevím, zdali ho mám vložit do nějakého systému hlášení chyb v PHP.
Zdá se, že funkce iconv_strlen() nepracuje s řetězci kratšími než 3 znaky. Přijde mi to podivné chování. Ještě to jdu zkoumat.
Štěpán Svoboda:
např.
<?php
$s = "žu";
echo $iconv_strlen($s, 'UTF-8');
// Unkown Error 20
$s = "žuk";
echo $iconv_strlen($s, 'UTF-8');
// 3
?>
Crempa:
Ahoj,
může mě prosím někdo vysvětlit přesnou funkci přepínače "u" u perl comp. regular funkci?
Z dokumentace jsem pochopil, že je při jeho použití brán text v šabloně jako by byl kódován v utf-8, znamená to teda že pokud bude celej soubor scriptu kódován v utf-8, tak je tenhle přepínač zbytečnej? Nebo je to všechno jinak :-) ?
Díky
PS: zajimave pocteni na tema UTF-8 v PHP, treba se to nekomu bude hodit
http://www.phpwact.org/php/i18n/utf-8
Jakub Vrána :
Naopak – když je skript v kódování UTF-8, mohu přepínač bez obav použít a získat tak funkčnost, kterou zajišťuje.
Crempa:
aha, diky
popravde ale stejne nemuzu najit situaci ve ktere by to bez prepinace pracovalo jinak nez s prepinacem, i v clanku uvedeny priklad funguje myslim spravne i bez pouziti prepinace
Jakub Vrána :
Např. řetězec "ěš" má v UTF-8 čtyři bajty, i když to jsou jenom dva znaky. Takže bez přepínače /u by to vzalo i kratší adresy.
Crempa:
ahaa, tak uz je to jasne, diky moc za nakopnuti
Vladka:
Dobrý deň, vedeli by ste mi niekto pomôcť pri dekódovaní textu ﭺﭡﭲﭡﭧﭯﭺﭡ lebo viem si jednotlivé znaky previesť do UTF-8 no neviem, či je možné z toho dosťať text, poprípade ako....vopred ďakujem každému za pomoc...
Al Arabbia:
Vladka to čo s tým vieš urobiť ti úplne stačí na "tvoj" problém :)
Diskuse je zrušena z důvodu spamu.