Java a čeština? Unicode! |
Světový standard kódování znaků Unicode Worldwide Character Standard zavedlo Unicode Consorcium jako systém znaků určený pro podporu výměny, zpracování a zobrazování psaného textu v rozličných jazykových verzích moderního světa.
Oproti kódování ASCII a dalším jednobajtovým kódováním, ve kterých je každý znak uložen na 8 bitech, je v kódováních Unicode jeden znak uložen na jednom a více bajtech. Znaky Unicode je do bajtů možné kódovat vícero kódováními: kódovacími schématy Unicode Transformation Formats (UTF) nebo Universal Character Set (UCS). Mezi nejdůležitější patří UTF-8, které kóduje znaky na jeden až čtyři bajty a je zajímavé tím, že je kompatibilní s ASCII, UTF-16, které znaky kóduje do dvou nebo čtyř bajtů nebo UCS-4/UTF-32, což jsou shodná kódování přiřazující znakům vždy čtyři bajty.
Unicode je značně univerzální a obsahuje vlastně znaky všech národních abeced (Ameriky, Evropa, Střední Východ, Afrika, Asie a Tichomoří). Pro nás je samozřejmě důležité že i ty naše špecifické - česko - slovenské.
Pro kódování češtiny se používají i jiná kódování: je to především Windows-1250 (používané ve Windows), ISO-8859-2 (dříve zvané Latin2 nebo Latin 2) používané na operačním systému Linux a další. V Javě je samozřejmě možné mezi jednotlivými kódováními převádět.
Pokud jste někdy programovali v Javě, určitě jste narazili na problém jak nahnat do svých aplikací, appletů a konfiguračních souborů spoustu všelijakých znaků se všelijak zkroucenými znamínky v záhlaví. Tento problém samozřejmě není neřešitelný a já se jej pokusím teď rozebrat.
V Javě jsou všechny znaky (a taky stringy) reprezentovny právě pomocí Unicode, které se zapisují pomocí escape sekvencí takto
char ch = '\unnnn';
kde nnnn
je hexadecimální vyjádření pozice znaku v tabulce Unicode.
Za normálních okolností tento zápis zřejmě nepoužijete, protože překladač si ASCII znaky "konvertuje" sám, problém nastává až s národními (českými) znaky. Tady už tento zápis použít musíte.
Zápis ě (e s háčkem) pomocí escape sekvence v Unicode vypadá
char ch = '\u011B';
Pokud chceme napsat slůvko pěkně použijeme konstrukci
String s = "p" + '\u011B' + "kn" + '\u011B';
Asi si řeknete, že je to poměrně složité, ale odměnou vám je, že takovéto české znaky
budou čitelné skutečně na všech platformách.
Samozřejmě za předpokladu, že je k dispozici font s odpovídajícími (českými) znaky!
Novější verze kompilátoru Javy (určitě od verze 1.4) umožňují použití přepínače --encoding kódování
, který umožní zapisovat zdrojový kód ve zvoleném kódování, a kompilátor sám provede konverzi do Unicode. Rovněž vývojová prostředí vám dovolí nastavit kódování zdrojového textu, a například Eclipse pro Windows správně samo nastaví kódování na Windows-1250.
Pokud do Javovského programu potřebujeme načíst soubor, který není kódován v Unicode, s úspěchem využijeme druhý parametr konstruktoru třídy InputStreamReader
, kde specifikujeme kódování souboru.
BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream("soubor.txt"), "windows-1250"));
V servletech je nutné nastavit vámi používané kódování nejenom pro response, ale i pro request.
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
Ve svých JSP stránkách uvádějte používané kódování pomocí direktivy
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
Tuto direktivu nezapomeňte vložit i do souborů, které vkládáte pomocí <%@ include file="soubor.html" %>
.
Většina databází (a databázových driverů), ke kterým se přistupuje přes JDBC, nemá se správným překódováním znaků mezi kódováním databáze a Javou problém (PostgreSQL, Oracle,...), nicméně MySQL vyžaduje použité kódování uvést v connection stringu. Pokud databáze používá kódování Windows 1250, bude to vypadat takto:
jdbc:mysql://hostname/database?characterEncoding=Cp1250
Pro ISO 8859-2 použijeme hodnotu ISO8859_2
.
Pokud databáze používá UTF-8, je třeba ještě přidat parametr useUnicode=true
:
jdbc:mysql://hostname/database?useUnicode=true&characterEncoding=UTF-8
Občas se hodí dikaritiku z textu odstranit (z č udělat c).
V Javě verze 1.4 a 5 je třída Normalizer
, která je součástí nestandardního balíčku sun.text:
String bez = Normalizer.normalize("žluťoučký", Normalizer.DECOMP, 0).replaceAll("[^\\p{ASCII}]","");
V Javě od verze 6 pak je pak přesunuta java.text.Normalizer a má trochu jinou syntaxi:
String bez = Normalizer.normalize("žluťoučký", Form.NFD).replaceAll("[^\\p{ASCII}]","");
Můžeme také použít ICU (International Components for Unicode). (Kompletní ICU4J má přes 3MB, ale samotný jar s transliterátorem má cca 700kB, viz How to modularize ICU4J.)
Transliterator t = Transliterator.getInstance("NFD; [:Nonspacing Mark:] Remove; NFC");
String bez = t.transliterate("žluťoučký");
Znak | hexa hodnota | Znak | hexa hodnota | Znak | hexa hodnota | ||
---|---|---|---|---|---|---|---|
Á | 00C1 | Í | 00CD | Ť | 0164 | ||
á | 00E1 | í | 00ED | ť | 0165 | ||
Č | 010C | Ň | 0147 | Ú | 00DA | ||
č | 010D | ň | 0148 | ú | 00FA | ||
Ď | 010E | Ó | 00D3 | Ů | 016E | ||
ď | 010F | ó | 00F3 | ů | 016F | ||
É | 00C9 | Ř | 0158 | Ý | 00DD | ||
é | 00E9 | ř | 0159 | ý | 00FD | ||
Ě | 011A | Š | 0160 | Ž | 017D | ||
ě | 011B | š | 0161 | ž | 017E |
A kdo mi nevěří, tak tady jsou dvě originální Unicode tabulky se znaky, které jsou pro nás důležité.
Další tabuldy znaků 0180 - 0217 a 2100 - 2138
Šťastné a veselé programování přeje Martiner
Prameny: David Flanagan: Programování v jazyce Java a
http://www.unicode.org
Název a loga Unicode jsou nepochybně registrovanými značkami Unicode Consorcium.
Webhosting zajišťuje Macroware s.r.o.