Počítače Okna Internet

Ruská písmena v tabulce kódů systému Windows. Kódování cyrilice - ruština

Kódování

Když jsem poprvé začal programovat v C, můj první program (kromě HelloWorld) byl transkódovací program textové soubory od hlavního GOST kódování (pamatujete si tohle? :-) na alternativní. Bylo to v roce 1991. Od té doby se mnohé změnilo, ale bohužel tyto programy za posledních 10 let neztratily svůj význam. V různých kódováních již bylo nahromaděno příliš mnoho dat a je použito příliš mnoho programů, které mohou pracovat pouze s jedním. Existuje nejméně tucet různých kódování pro ruský jazyk, což činí problém ještě více matoucím.

Kde se všechna tato kódování vzala a k čemu jsou? Počítače ze své podstaty mohou pracovat pouze s čísly. Aby bylo možné ukládat písmena do paměti počítače, je nutné každému písmenu přiřadit určité číslo (přibližně stejný princip byl použit ještě předtím, než se objevily počítače - pamatujte si stejnou morseovku). Navíc je žádoucí menší číslo - čím méně binárních číslic je použito, tím efektivněji lze paměť využít. Tato korespondence mezi sadou znaků a čísel je ve skutečnosti kódováním. Touha zachránit paměť za každou cenu, stejně jako nejednotnost různých skupin počítačových vědců, vedla k současnému stavu věcí. Nyní je nejběžnější metodou kódování použít jeden bajt (8 bitů) pro jeden znak, který určuje celkový počet znaků ve 256. Sada prvních 128 znaků je standardizována (sada ASCII) a je stejná ve všech běžných kódováních (ta kódování, kde ještě není tak prakticky mimo provoz). Anglikánská písmena a interpunkční symboly jsou v tomto rozmezí, což určuje jejich úžasnou schopnost přežít v počítačových systémech :-). Jiné jazyky nejsou tak šťastné - všechny se musí schoulit ve zbývajících 128 číslech.

Unicode

Na konci osmdesátých let si mnozí uvědomili potřebu vytvořit jednotný standard pro kódování znaků, což vedlo ke vzniku Unicode. Unicode je pokus o opravu konkrétního čísla pro konkrétní znak jednou provždy. Je jasné, že 256 znaků se sem při vší touze nevejde. Poměrně dlouho se zdálo, že 2 bajty (65 536 znaků) by měly stačit. Ale ne - nejnovější verze standardu Unicode (3.1) již definuje 94 140 znaků. Pro takový počet znaků již pravděpodobně musíte použít 4 bajty (4294967296 znaků). Na chvíli možná dost ... :-)

Do sady Znaky Unicode zahrnuje všechny druhy písmen se všemi druhy pomlček a papendyulki, řecké, matematické, hieroglyfy, pseudografické symboly atd. atd. Včetně našich oblíbených cyrilice (rozsah hodnot je 0x0400-0x04ff). Na této straně tedy neexistuje žádná diskriminace.

Pokud vás zajímají konkrétní kódy znaků, je vhodné k jejich zobrazení použít program „Character Map“ od WinNT. Například zde je azbuka:

Pokud máte jiný operační systém nebo vás zajímá oficiální výklad, pak úplné grafy najdete na oficiálním webu Unicode (http://www.unicode.org/charts/web.html).

Typy znaků a bajtů

Java má pro znaky samostatný datový typ char 2 bajty. To často způsobuje zmatek v myslích začátečníků (zvláště pokud dříve programovali v jiných jazycích, jako je C / C ++). Důvodem je, že většina ostatních jazyků používá ke zpracování znaků jednobajtové datové typy. Například v C / C ++ se char většinou používá jak pro zpracování znaků, tak pro zpracování bajtů - neexistuje žádné oddělení. Java má svůj vlastní typ pro bajty - typ bajtů. Char C na bázi tedy odpovídá bajtu Java a znak Java ze světa C je nejblíže typu wchar_t. Je nutné jasně oddělit pojmy postav a bajtů - v opačném případě je zaručeno nedorozumění a problémy.

Java používá pro kódování znaků téměř od svého vzniku Standard Unicode... Funkce knihovny Java očekávají znaky char reprezentované Unicode kódy... V zásadě tam samozřejmě můžete nacpat cokoli - čísla jsou čísla, procesor všechno vydrží, ale při jakémkoli zpracování budou funkce knihovny fungovat za předpokladu, že byly dány Kódování Unicode... Můžete tedy bezpečně předpokládat, že kódování znaků je pevné. Ale to je uvnitř JVM. Když jsou data čtena zvenčí nebo předávána zvenčí, mohou být reprezentována pouze jedním typem - typem bajtů. Všechny ostatní typy jsou vytvořeny z bajtů v závislosti na použitém formátu dat. Tady vstupuje do hry kódování - v Javě je to jen datový formát pro přenos znaků, který slouží k vytváření dat typu char. Pro každou kódovou stránku má knihovna 2 třídy převodu (ByteToChar a CharToByte). Tyto třídy jsou v balíčku sun.io. Pokud při převodu z char na byte nebyl nalezen žádný odpovídající znak, je nahrazen znakem?

Mimochodem, tyto soubory kódové stránky v některých raných verzích JDK 1.1 obsahují chyby, které způsobují chyby převodu nebo dokonce výjimky za běhu. Týká se to například kódování KOI8_R. Nejlepší je přitom změnit verzi na novější. Soudě podle popisu společnosti Sun byla většina těchto problémů vyřešena v JDK 1.1.6.

Před JDK 1.4 byla sada dostupných kódování určena pouze prodejcem JDK. Počínaje verzí 1.4 se objevilo nové API (balíček java.nio.charset), pomocí kterého si již můžete vytvořit vlastní kódování (například podporovat zřídka používané, ale pro vás strašně nutné).

Řetězcová třída

Ve většině případů Java používá k reprezentaci řetězců objekt typu java.lang.String. Toto je běžná třída, která interně ukládá řadu znaků (char) a která obsahuje mnoho užitečných metod pro manipulaci se znaky. Nejzajímavější jsou konstruktory s bajtovým polem jako prvním parametrem a metody getBytes (). Pomocí těchto metod můžete provádět převody z bajtových polí na řetězce a naopak. Aby bylo možné určit, které kódování použít současně, mají tyto metody řetězcový parametr, který nastavuje jeho název. Zde například můžete převést bajty z KOI-8 na Windows-1251:

// Data kódovaná KOI-8 byte koi8Data = ...; // Převod z KOI-8 na UnicodeŘetězec řetězce = nový řetězec (koi8Data, "KOI8_R"); // Převod z Unicode na Windows-1251 byte winData = string.getBytes ("Cp1251");

Seznam 8bitových kódování dostupných v moderních JDK a podpůrných ruských písmen naleznete níže v sekci.

Protože kódování je datový formát pro znaky, existují kromě známých 8bitových kódování v Javě také vícebajtová kódování na stejné úrovni. Patří sem UTF-8, UTF-16, Unicode atd. Například takto můžete získat bajty ve formátu UnicodeLittleUnmarked (16bitové kódování Unicode, nejprve nízký bajt, žádný znak pořadí bajtů):

// Převod z Unicode na Unicode byte data = string.getBytes ("UnicodeLittleUnmarked");

Je snadné udělat chybu s takovými převody - pokud kódování bajtových dat neodpovídá zadanému parametru při převodu z bajtu na char, pak překódování nebude provedeno správně. Někdy poté můžete vytáhnout správné znaky, ale častěji se část dat nenávratně ztratí.

Ve skutečném programu není vždy vhodné specifikovat kódovou stránku explicitně (i když je spolehlivější). Za tímto účelem bylo zavedeno výchozí kódování. Ve výchozím nastavení závisí na systému a jeho nastavení (kódování Cp1251 je přijato pro ruský Windows) a ve starých JDK je možné jej změnit nastavením vlastnosti souboru system.encoding. V JDK 1.3 změna tohoto nastavení někdy funguje, někdy ne. To je způsobeno následujícími příčinami: zpočátku se nastavení file.encoding nastaví podle regionálních nastavení počítače. Výchozí kódovací reference je při první konverzi interně zapamatována. V tomto případě se používá file.encoding, ale k tomuto převodu dochází ještě před použitím spouštěcích argumentů JVM (ve skutečnosti při jejich analýze). Ve skutečnosti Sun říká, že tato vlastnost odráží systémové kódování a neměla by být změněna na příkazovém řádku (viz například komentáře k BugID). V JDK 1.4 Beta 2 však změna tohoto nastavení opět začala mít účinek. Co je to, vědomá změna nebo vedlejší účinek, který může znovu zmizet - sluneční ovce dosud nedaly jasnou odpověď.

Toto kódování se používá, pokud název stránky není výslovně uveden. To by mělo být vždy pamatováno - Java se nebude pokoušet předpovídat kódování bajtů, které předáváte, aby vytvořil String (také nebude schopen číst vaše myšlenky na to :-). Pouze používá aktuální výchozí kódování. Protože toto nastavení je stejné pro všechny transformace, někdy můžete narazit na potíže.

Chcete -li převést z bajtů na znaky a naopak, použijte pouze těmito metodami. Ve většině případů nelze použít jednoduchý převod typu - kódování znaků nebude bráno v úvahu. Jednou z nejběžnějších chyb je například čtení dat po bajtech pomocí metody read () z InputStream a následné přenesení výsledné hodnoty na typ char:

InputStream je = ..; int b; StringBuffer sb = new StringBuffer (); while ((b = is.read ())! = - 1) (sb.append ((char) b); // <- так делать нельзя ) Řetězec s = sb.toString ();

Věnujte pozornost castingu - „(char) b“. Bajtové hodnoty se místo překódování jednoduše zkopírují do znaku (rozsah hodnot je 0-0xFF, nikoli ten, kde je umístěna azbuka). Toto kopírování odpovídá kódování ISO-8859-1 (které jedna ku jedné odpovídá prvním 256 hodnotám Unicode), což znamená, že můžeme předpokládat, že jej tento kód jednoduše používá (místo toho, ve kterém znaky v původní data jsou skutečně zakódována). Pokud se pokusíte zobrazit přijatou hodnotu, budou na obrazovce buď otázky, nebo krakozyably. Například při čtení řetězce „ABC“ v kódování Windows lze snadno zobrazit něco takového: „АÁВ“. Tento druh kódu často píší programátoři na Západě - funguje s anglickými písmeny a dobře. Oprava tohoto kódu je snadná - stačí vyměnit StringBuffer za ByteArrayOutputStream:

InputStream je = ..; int b; ByteArrayOutputStream baos = nový ByteArrayOutputStream (); while ((b = is.read ())! = - 1) (baos.write (b);) // Převod bajtů na řetězec pomocí výchozího kódováníŘetězec s = baos.toString (); // Pokud potřebujete konkrétní kódování, stačí ho zadat při volání toString (): // // s = baos.toString ("Cp1251");
Další informace o běžných chybách najdete v části.

8bitové kódování ruských písmen

Zde jsou hlavní 8bitová kódování ruských písmen, která se rozšířila:

Kromě hlavního jména lze použít i synonyma. Jejich sada se může v různých verzích JDK lišit. Zde je seznam z JDK 1.3.1:

  • Cp1251:
    • Windows-1251
  • Cp866:
    • IBM866
    • IBM-866
    • CP866
    • CSIBM866
  • KOI8_R:
    • KOI8-R
    • CSKOI8R
  • ISO8859_5:
    • ISO8859-5
    • ISO-8859-5
    • ISO_8859-5
    • ISO_8859-5: 1988
    • ISO-IR-144
    • 8859_5
    • cyrilice
    • CSISOLatinKyrilská
    • IBM915
    • IBM-915
    • Cp915

Synonyma navíc na rozdíl od hlavního jména nerozlišují velká a malá písmena - to je rys implementace.

Stojí za zmínku, že tato kódování nemusí být u některých JVM k dispozici. Můžete si například stáhnout dvě různé verze JRE z webu Sun - USA a International. V americké verzi existuje jen minimum-ISO-8859-1, ASCII, Cp1252, UTF8, UTF16 a několik variací dvoubajtového Unicode. Všechno ostatní je k dispozici pouze v mezinárodní verzi. Někdy kvůli tomu můžete při spuštění programu narazit na hrábě, i když nepotřebuje ruská písmena. Typická chyba, ke které dochází při tom:

Při inicializaci VM java / lang / ClassNotFoundException došlo k chybě: sun / io / ByteToCharCp1251

Vzniká, protože není těžké uhodnout, vzhledem k tomu, že se JVM na základě ruského regionálního nastavení pokouší nastavit výchozí kódování v Cp1251, ale protože třída takové podpory v americké verzi chybí, přirozeně se rozpadá.

Soubory a datové toky

Stejně jako jsou bajty koncepčně oddělené od znaků, Java rozlišuje mezi bajtovými toky a toky znaků. Práce s bajty je reprezentována třídami, které přímo nebo nepřímo dědí třídy InputStream nebo OutputStream (plus jedinečnou třídu RandomAccessFile). Práci se symboly reprezentuje sladký pár tříd Reader / Writer (a jejich potomci, samozřejmě).

Proudy bajtů se používají ke čtení / zápisu nepřevedených bajtů. Pokud víte, že bajty jsou pouze znaky v určitém kódování, můžete použít speciální třídy převaděčů InputStreamReader a OutputStreamWriter, abyste získali proud znaků a pracovali s ním přímo. To je obvykle užitečné pro soubory prostého textu nebo při práci s mnoha síťovými protokoly internetu. V tomto případě je kódování znaků zadáno v konstruktoru třídy převaděče. Příklad:

// Řetězec Unicode Řetězec řetězce = "..."; // Napište řetězec do textového souboru v kódování Cp866 PrintWriter pw = nový PrintWriter // třída s metodami pro zápis řetězců(nový OutputStreamWriter // převodník tříd(nový FileOutputStream ("file.txt"), "Cp866"); pw.println (řetězec); // zapište řádek do souboru pw.close ();

Pokud stream může obsahovat data v různých kódováních nebo jsou znaky smíchány s jinými binárními daty, pak je lepší číst a zapisovat bajtová pole a pro převod použít již zmíněné metody třídy String. Příklad:

// Řetězec Unicode Řetězec řetězce = "..."; // Napište řetězec do textového souboru ve dvou kódováních (Cp866 a Cp1251) OutputStream os = nový FileOutputStream ("file.txt"); // třída pro zápis bajtů do souboru // Napište řetězec v kódování Cp866 os.write (string.getBytes ("Cp866")); // Napište řetězec v kódování Cp1251 os.write (string.getBytes ("Cp1251")); os.close ();

Konzolu v Javě tradičně představují streamy, ale bohužel ne znaky, ale bajty. Faktem je, že proudy znaků se objevily pouze v JDK 1.1 (spolu s celým mechanismem kódování) a přístup k I / O konzoly byl navržen v JDK 1.0, což vedlo ke vzniku podivína v podobě třídy PrintStream. Tato třída se používá v proměnných System.out a System.err, které ve skutečnosti umožňují přístup k výstupu do konzoly. Podle všeho je to proud bajtů, ale se spoustou metod pro psaní řetězců. Když do něj napíšete řetězec, převede se na bajty pomocí výchozího kódování, což je v případě systému Windows obvykle nepřijatelné - výchozí kódování bude Cp1251 (Ansi) a pro okno konzoly je obvykle nutné použít Cp866 ( OEM). Tato chyba byla zaregistrována již v 97. roce (), ale zdá se, že sluneční ovečky nespěchají na její opravu. Protože neexistuje žádná metoda pro nastavení kódování v PrintStream, k vyřešení tohoto problému můžete standardní třídu nahradit vlastní metodou System.setOut () a System.setErr (). Například zde je obvyklý začátek v mých programech:

... public static void main (String args) ( // Nastavte výstup zpráv konzoly v požadovaném kódování try (String consoleEnc = System.getProperty ("console.encoding", "Cp866"); System.setOut (new CodepagePrintStream (System.out, consoleEnc)); System.setErr (new CodepagePrintStream (System.err, consoleEnc)); ) catch (UnsupportedEncodingException e) (System.out.println ("Nelze nastavit kódovou stránku konzoly:" + e);) ...

Zdroje třídy CodepagePrintStream najdete na tomto webu: CodepagePrintStream.java.

Pokud si formát dat vytváříte sami, doporučuji použít jedno z vícebajtových kódování. Nejpohodlnějším formátem je obvykle UTF8 - prvních 128 hodnot (ASCII) v něm je zakódováno v jednom bajtu, což často může výrazně snížit celkové množství dat (ne nadarmo se toto kódování bere jako základ v svět XML). UTF8 má však jednu nevýhodu - požadovaný počet bajtů závisí na kódu znaku. Pokud je to důležité, můžete použít jeden z dvoubajtových formátů Unicode (UnicodeBig nebo UnicodeLittle).

Databáze

Aby bylo možné správně číst znaky z databáze, obvykle stačí sdělit ovladači JDBC požadované kódování znaků v databázi. Jak přesně závisí na konkrétním ovladači. V dnešní době již mnoho řidičů toto nastavení na rozdíl od nedávné minulosti podporuje. Zde je několik příkladů, o kterých vím.

Most JDBC-ODBC

Toto je jeden z nejčastěji používaných ovladačů. Most od JDK 1.2 a starší lze snadno nakonfigurovat na požadované kódování. To se provádí přidáním další vlastnosti charSet do sady parametrů předaných k otevření připojení k základně. Výchozí hodnota je file.encoding. To se provádí takto:

// Navažte připojení

Ovladač Oracle 8.0.5 JDBC-OCI pro Linux

Při příjmu dat z databáze tento ovladač určuje „své“ kódování pomocí proměnné prostředí NLS_LANG. Pokud tato proměnná není nalezena, pak předpokládá, že kódování je ISO-8859-1. Jde o to, že NLS_LANG by měla být proměnná prostředí (nastavená příkazem set), nikoli vlastnost systému Java (jako file.encoding). V případě použití ovladače uvnitř servletového motoru Apache + Jserv lze proměnnou prostředí nastavit v souboru jserv.properties:

wrapper.env = NLS_LANG = American_America.CL8KOI8R
Informace o tom poslal Sergej Bezrukov, za což mu patří zvláštní poděkování.

Ovladač JDBC pro práci s DBF (zyh.sql.dbf.DBFDriver)

Tento řidič se teprve nedávno naučil pracovat s ruskými písmeny. I když hlásí getPropertyInfo (), že chápe vlastnost charSet, je to fikce (alespoň ve verzi z 30. 7. 2001). Ve skutečnosti můžete kódování přizpůsobit nastavením vlastnosti CODEPAGEID. Pro ruské znaky jsou k dispozici dvě hodnoty - „66“ pro Cp866 a „C9“ pro Cp1251. Příklad:

// Základní parametry připojení Vlastnosti connInfo = nové Properties (); connInfo.put ("CODEPAGEID", "66"); // Kódování Cp866 // Navažte připojení Připojení db = DriverManager.getConnection ("jdbc: DBF: / C: / MyDBFFiles", connInfo);
Pokud máte soubory DBF ve formátu FoxPro, pak mají svá vlastní specifika. Faktem je, že FoxPro ukládá do záhlaví souboru ID kódové stránky (bajt s ofsetem 0x1D), která byla použita k vytvoření DBF. Při otevírání tabulky používá ovladač hodnotu z hlavičky, nikoli parametr „CODEPAGEID“ (parametr se v tomto případě používá pouze při vytváření nových tabulek). Aby vše správně fungovalo, musí být soubor DBF vytvořen se správným kódováním - jinak budou problémy.

MySQL (org.gjt.mm.mysql.Driver)

S tímto ovladačem je vše také velmi jednoduché:

// Základní parametry připojení Vlastnosti connInfo = new Poperties (); connInfo.put ("uživatel", uživatel); connInfo.put ("heslo", heslo); connInfo.put ("useUnicode", "true"); connInfo.put ("characterEncoding", "KOI8_R"); Připojení conn = DriverManager.getConnection (dbURL, rekvizity);

InterBase (interbase.interclient.Driver)

U tohoto ovladače funguje parametr „charSet“:
// Základní parametry připojení Vlastnosti connInfo = nové Vlastnosti (); connInfo.put ("uživatel", uživatelské jméno); connInfo.put ("heslo", heslo); connInfo.put ("charSet", "Cp1251"); // Navažte připojení Připojení db = DriverManager.getConnection (dataurl, connInfo);

Při vytváření databáze a tabulek však nezapomeňte zadat kódování znaků. Pro ruský jazyk můžete použít hodnoty „UNICODE_FSS“ nebo „WIN1251“. Příklad:

VYTVOŘIT DATABÁZI "E: \ ProjectHolding \ DataBase \ HOLDING.GDB" PAGE_SIZE 4096 SADA VÝCHOZÍCH ZNAKŮ UNICODE_FSS; VYTVOŘIT TABULKU RUSKÉ_Slovo („NAME1“ VARCHAR (40) SADA ZNAKŮ UNICODE_FSS NENÍ NULÁ, VARCHAR „NAME2“ (40) SADA ZNAKŮ WIN1251 NENÍ NULÁ, PRIMÁRNÍ KLÍČ („NAME1“));

Ve verzi 2.01 InterClient je chyba - třídy prostředků se zprávami pro ruský jazyk tam nejsou správně kompilovány. S největší pravděpodobností vývojáři při kompilaci jednoduše zapomněli zadat zdrojové kódování. Tuto chybu lze opravit dvěma způsoby:

  • Místo interclient.jar použijte interclient-core.jar. Současně prostě nebudou žádné ruské zdroje a ty anglické budou vyzvednuty automaticky.
  • Překompilovat soubory do normálního Unicode. Analýza souborů třídy je nevděčný úkol, takže je lepší použít JAD. Bohužel JAD, pokud narazí na znaky ze sady ISO-8859-1, je vydá v 8místném kódování, takže nebudete moci použít standardní kodér native2ascii-musíte si napsat vlastní (program Decode). Pokud se s těmito problémy nechcete trápit, můžete jednoduše vzít hotový soubor se zdroji (záplatovaná jar s ovladačem - interclient.jar, oddělené třídy zdrojů - interclient -rus.jar).

Ale i po vyladění ovladače JDBC na požadované kódování se v některých případech můžete dostat do potíží. Například při pokusu použít nádherné nové rolovací kurzory standardu JDBC 2 v můstku JDBC-ODBC z JDK 1.3.x rychle zjistíte, že tam ruská písmena jednoduše nefungují (metoda updateString ()).

S touto chybou je spojen malý příběh. Když jsem to poprvé objevil (pod JDK 1.3 rc2), zaregistroval jsem to u BugParade (). Když vyšla první beta verze JDK 1.3.1, byla tato chyba označena jako opravená. Potěšení, stáhl jsem si tuto beta verzi, spustil test - nefunguje. Napsal jsem o tom Slunným ovcím - v reakci na to mi napsali, že oprava bude zahrnuta v budoucích vydáních. Dobře, pomyslel jsem si, počkejme. Čas plynul, byla vydána verze 1.3.1 a poté beta 1.4. Nakonec jsem si udělal čas na kontrolu - už to nefunguje. Matka, matka, matka ... - ozvěna se ozývala obvyklým způsobem. Po rozzlobeném dopise Sunu zavedli novou chybu (), kterou dali indické větvi na roztrhání. Indiáni si pohrávali s kódem a řekli, že vše bylo opraveno v 1.4 beta3. Stáhl jsem si tuto verzi, spustil pod ní testovací případ, tady je výsledek -. Jak se ukázalo, beta3, která je distribuována na webu (build 84), není beta3, kde byla zahrnuta finální oprava (build 87). Nyní slibují, že oprava bude zahrnuta v 1.4 rc1 ... No, obecně, rozumíte :-)

Ruská písmena ve zdrojích programů Java

Jak již bylo zmíněno, program při provádění používá Unicode. Zdrojové soubory jsou psány v běžných editorech. Používám Far, pravděpodobně máte svého oblíbeného editora. Tyto editory ukládají soubory v 8bitovém formátu, což znamená, že uvažování podobné výše uvedenému platí i pro tyto soubory. Různé verze překladačů provádějí převod znaků mírně odlišně. Dřívější verze JDK 1.1.x používají nastavení file.encoding, které lze přepsat nestandardní volbou -J. V novějších (jak uvádí Denis Kokarev - od 1.1.4) byl zaveden další parametr -encoding, pomocí kterého můžete určit použité kódování. V kompilovaných třídách jsou řetězce zastoupeny ve formě Unicode (přesněji v upravené verzi formátu UTF8), takže to nejzajímavější se děje během kompilace. Proto je nejdůležitější zjistit, v jakém kódování jsou vaše zdrojové kódy a při kompilaci zadat správnou hodnotu. Ve výchozím nastavení bude použit stejný notoricky známý soubor. Kódování. Příklad volání kompilátoru:

Kromě použití tohoto nastavení existuje ještě jedna metoda - zadat písmena ve formátu „\ uXXXX“, kde je uveden kód znaku. Tato metoda funguje se všemi verzemi a k ​​získání těchto kódů můžete použít standardní nástroj.

Pokud používáte jakékoli IDE, pak může mít své vlastní závady. Tato IDE často používají výchozí kódování pro čtení / ukládání zdrojů - věnujte proto pozornost regionálnímu nastavení vašeho OS. Kromě toho mohou existovat zjevné chyby - například docela dobrý CodeGuide v měřítku IDE špatně stráví velké ruské písmeno „T“. Vestavěný analyzátor kódu bere toto písmeno jako uvozovku, což vede k tomu, že správný kód je vnímán jako chybný. Můžete s tím bojovat (nahrazením písmene „T“ jeho kódem „\ u0422“), ale nepříjemné. Zjevně se někde uvnitř analyzátoru používá explicitní převod znaků na bajty (jako: byte b = (byte) c), takže místo kódu 0x0422 (kód písmene „T“) je kód 0x22 ( kód dvojité uvozovky).

JBuilder má další problém, ale ten souvisí spíše s ergonomií. Faktem je, že v JDK 1.3.0, pod kterým JBuilder standardně běží, existuje chyba (), kvůli které nově vytvořená okna GUI po aktivaci automaticky zahrnují rozložení klávesnice v závislosti na regionálním nastavení operačního systému. Tito. pokud máte ruské regionální nastavení, pak se bude neustále pokoušet přepnout na ruské rozložení, které překáží při psaní programů. Web JBuilder.ru má několik oprav, které mění aktuální národní prostředí v JVM na Locale.US, ale nejlepším způsobem je upgradovat na JDK 1.3.1, který tuto chybu opravil.

Začínající uživatelé JBuilderu se také mohou setkat s takovým problémem - ruská písmena jsou uložena jako kódy „\ uXXXX“. Abyste tomu zabránili, v dialogu Výchozí vlastnosti projektu na kartě Obecné v poli Kódování změňte Výchozí na Cp1251.

Pokud pro kompilaci nepoužíváte standardní javac, ale jiný překladač - věnujte pozornost tomu, jak provádí převod znaků. Některé verze kompilátoru IBM jikes například nechápou, že existují jiná kódování než ISO-8859-1 :-). V tomto ohledu existují verze záplatované, ale často je tam také sešité nějaké kódování - neexistuje takové pohodlí jako v javacu.

JavaDoc

Ke generování dokumentace HTML pro zdrojový kód se používá obslužný program javadoc, který je součástí standardní distribuce JDK. Chcete -li zadat kódování, má až 3 parametry:

  • -encoding - toto nastavení nastavuje zdrojové kódování. Výchozí hodnota je file.encoding.
  • -docencoding - toto nastavení určuje kódování generovaných souborů HTML. Výchozí hodnota je file.encoding.
  • -charset - toto nastavení určuje znakovou sadu, která bude zapsána do hlaviček generovaných souborů HTML ( ). Očividně by to mělo být stejné jako předchozí nastavení. Pokud toto nastavení vynecháte, metaznačka nebude přidána.

Ruská písmena v souborech vlastností

Metody načítání zdrojů se používají ke čtení souborů vlastností, které fungují určitým způsobem. Ve skutečnosti se ke čtení používá metoda Properties.load, která nepoužívá file.encoding (zdrojový kód je pevně zakódován kódováním ISO-8859-1), takže jediným způsobem, jak určit ruská písmena, je použít „\ uXXXX“ formát a obslužný program.

V JDK 1.1 a 1.2 metoda Properties.save funguje odlišně. Ve verzích 1.1 jednoduše zahodil vysoký bajt, takže fungoval správně pouze s anglickými písmeny. 1.2 provede reverzní převod na "\ uXXXX" tak, aby fungoval zrcadleně na metodu načítání.

Pokud vaše soubory vlastností nejsou načteny jako prostředky, ale jako běžné konfigurační soubory, a nejste s tímto chováním spokojeni, existuje pouze jedna cesta ven, napište svůj vlastní zavaděč.

Ruská písmena v servletech.

K čemu jsou tytéž servlety, myslím, že víš. Pokud ne, je nejlepší si nejprve přečíst dokumentaci. Zde jsou popsány pouze zvláštnosti práce s ruskými písmeny.

Jaké jsou tedy funkce? Když Servlet odešle klientovi odpověď, existují dva způsoby, jak tuto odpověď odeslat - prostřednictvím OutputStream (metoda getOutputStream ()) nebo prostřednictvím PrintWriter (metoda getWriter ()). V prvním případě píšete pole bajtů, takže platí výše uvedené metody zápisu do streamů. V případě PrintWriter používá nastavené kódování. V každém případě musíte správně zadat kódování použité při volání metody setContentType (), aby došlo ke správné konverzi znaků na straně serveru. Tuto směrnici je nutné provést před voláním getWriter () nebo před prvním zápisem do OutputStream. Příklad:

// Nastaví kódování odpovědi // Všimněte si, že některé motory to neumožňují // mezera mezi ";" a "znaková sada" response.setContentType ("text / html; charset = UTF-8"); PrintWriter out = response.getWriter (); // Ladění výstupu názvu kódování ke kontrole out.println ("Kódování:" + response.getCharacterEncoding ()); ... out.close (); )

Jde o to dát klientovi odpovědi. Se vstupními parametry to bohužel není tak jednoduché. Vstupní parametry jsou kódovány bajtem prohlížeče podle typu MIME „application / x-www-form-urlencoded“. Jak řekl Alexey Mendelev, prohlížeče kódují ruská písmena pomocí aktuálně nastaveného kódování. A samozřejmě se o tom nic nehlásí. Proto například ve verzích JSDK od 2.0 do 2.2 toto není nijak kontrolováno a jaký druh kódování bude použit pro převod závisí na použitém enginu. Počínaje specifikací 2.3 bylo možné nastavit kódování pro javax.servlet.ServletRequest - metodu setCharacterEncoding (). Nejnovější verze Resin a Tomcat již tuto specifikaci podporují.

Pokud tedy máte štěstí a máte server s podporou Servlet 2.3, je vše celkem jednoduché:

public void doPost (požadavek HttpServletRequest, odpověď HttpServletResponse) vyvolá ServletException, IOException ( // Kódování zpráv request.setCharacterEncoding ("Cp1251"); Řetězcová hodnota = request.getParameter ("hodnota"); ...

Při aplikaci metody request.setCharacterEncoding () existuje jedna významná jemnost - musí být použita před první volání požadavku na data (například request.getParameter ()). Pokud použijete filtry, které zpracují požadavek, než dorazí do servletu, existuje nenulová šance, že jeden z filtrů může přečíst nějaký parametr z požadavku (například pro autorizaci) a request.setCharacterEncoding () v servletu nebude pracovat ...

Proto je ideologicky správnější napsat filtr, který nastaví kódování požadavku. Navíc musí být první v řetězci filtrů v souboru web.xml.

Příklad takového filtru:

import java.io. *; import java.util. *; import javax.servlet. *; import javax.servlet.http. *; veřejná třída CharsetFilter implementuje filtr (// kódování soukromého kódování řetězců; public void init (konfigurace FilterConfig) vyvolá ServletException ( // čtení z konfigurace encoding = config.getInitParameter ("requestEncoding"); // pokud není nainstalován, nainstalujte Cp1251 if (encoding == null) encoding = "Cp1251"; ) public void doFilter (ServletRequest request, ServletResponse response, FilterChain next) throws IOException, ServletException (request.setCharacterEncoding (encoding); next.doFilter (request, response);) public void destru () ())

A jeho konfigurace v web.xml:

Charsetový filtr CharsetFilter Charsetový filtr /*

Pokud máte smůlu a máte více stará verze- k dosažení výsledku budete muset zvrátit:

    Originální způsob práce s kódováním nabízí ruský Apache - je přesně popsáno jak.

  • FOP

    Pokud program nikde nefunguje, pak je problém pouze v něm a ve vašich rukou. Pečlivě si přečtěte vše, co bylo napsáno výše, a podívejte se. Pokud se problém projevuje pouze v konkrétním prostředí, pak může být záležitost v nastavení. Kde přesně záleží na tom, jakou grafickou knihovnu používáte. Pokud může pomoci AWT - správná konfigurace souboru font.properties.ru. Příklad správného souboru lze převzít z Javy 2. Pokud tuto verzi nemáte, můžete si ji stáhnout z tohoto webu: Verze Windows, Linux verze (viz také níže). Tento soubor určuje písma a kódové stránky, které se mají použít. Pokud máte nainstalovanou ruskou verzi operačního systému, přidejte tento soubor na místo, kde se nachází soubor font.properties. Pokud se jedná o anglickou verzi, musíte buďto tento soubor přepsat místo souboru font.properties, nebo dodatečně změnit aktuální regionální nastavení na ruštinu. Někdy může nastavení -Duser.language = ru fungovat, ale častěji ne. Existují přibližně stejné problémy jako u file.encoding - zda funguje nebo ne, závisí na JDK (viz chyba podle čísla).

    S knihovnou Swing je vše jednodušší - vše v ní je čerpáno prostřednictvím subsystému Java2D. Je velmi snadné převést popisky ve standardních dialozích (JOptionPane, JFileChooser, JColorChooser) na ruštinu - stačí vytvořit několik souborů zdrojů. Už jsem to udělal, takže můžete vzít hotový soubor a přidat jej do lib \ ext nebo CLASSPATH. Jediný problém, se kterým jsem se setkal, je ten, že ve verzích JDK počínaje od 1.2 rc1 a 1.3 beta se ruská písmena nezobrazují pod Win9x při použití standardních písem (Arial, Courier New, Times New Roman atd.) Kvůli chybě v Java2D. Chyba je docela zvláštní - u standardních písem se obrázky písmen nezobrazují podle kódů Unicode, ale podle tabulky Cp1251 ( Ansi kódování). Tato chyba je zaregistrována v BugParade pod číslem. Ve výchozím nastavení Swing používá písma uvedená v souboru font.properties.ru, takže je stačí nahradit jinými a objeví se ruská písmena. Sada pracovních písem je bohužel malá - jedná se o písma Tahoma, Tahoma Bold a dvě sady písem z distribuce JDK - Lucida Sans * a Lucida Typewriter * (příklad souboru font.properties.ru). Jak se tato písma liší od standardních, mi není jasné.

    Od verze 1.3rc1 je tento problém již vyřešen, takže stačí aktualizovat JDK. JDK 1.2 je již velmi zastaralý, proto jej nedoporučuji používat. Je třeba také poznamenat, že původní verze Win95 je dodávána s fonty, která nepodporují Unicode - v této situaci můžete jednoduše kopírovat písma z Win98 nebo WinNT.

    Typické chyby nebo „kam zmizelo písmeno W?“

    Písmeno Sh.

    Tuto otázku („kam zmizelo písmeno W?“) Často pokládají začínající Java programátoři. Podívejme se, kam to opravdu nejčastěji chodí. :-)

    Zde je typický program ve stylu HelloWorld:

    test veřejné třídy (public static void main (String args) (System.out.println ("ИЦУКЕНГШЩЗХЪ");))
    ve Far uložte tento kód do souboru Test.java, zkompilujte ...
    C: \> javac Test.java
    a běž ...
    C: \> java Test YTsUKENG? ЩЗХЪ

    Co se stalo? Kam zmizelo písmeno W? Tady jde o to, že došlo ke vzájemné kompenzaci dvou chyb. Far textový editor ve výchozím nastavení vytvoří soubor kódovaný DOS (Cp866). Kompilátor javac používá ke čtení zdroje file.encoding (pokud není s klíčem -encoding uvedeno jinak). A v Prostředí Windows s ruským národním prostředím je výchozí kódování Cp1251. Toto je první chyba. V důsledku toho mají symboly v kompilovaném souboru Test.class nesprávné kódy. Druhá chyba je, že se pro výstup používá standardní PrintStream, který také používá nastavení z file.encoding, ale okno konzoly ve Windows zobrazuje znaky pomocí kódování DOS. Pokud by kódování Cp1251 bylo vzájemně platné, nedošlo by ke ztrátě dat. Ale znak W v Cp866 má kód 152, který není definován v Cp1251, a proto se mapuje na znak Unicode 0xFFFD. Při převodu zpět z char na byte je nahrazeno „?“.

    Na podobnou kompenzaci můžete narazit, pokud čtete znaky z textového souboru pomocí java.io.FileReader a poté je zobrazíte na obrazovce pomocí System.out.println (). Pokud byl soubor zapsán v kódování Cp866, pak výstup půjde správně, s výjimkou písmene Ш znovu.

    Přímý převod bajtů<->char.

    Tato chyba je oblíbená u zahraničních programátorů Java. Je to podrobně rozebráno na začátku popisu. Pokud se někdy podíváte na zdroje jiných lidí, vždy věnujte pozornost explicitnímu převodu typu - (byte) nebo (char). Na takových místech jsou často pohrabávány hrábě.

    Algoritmus pro hledání problémů s ruskými písmeny

    Pokud netušíte, kde ke ztrátě ruských písmen ve vašem programu může dojít, můžete zkusit další test. Jakýkoli program lze považovat za procesor vstupních dat. Ruská písmena jsou stejná data, obecně procházejí třemi fázemi zpracování: jsou odněkud načtena do paměti programu (vstup), zpracována uvnitř programu a zobrazena uživateli (výstup). Abyste určili místo problémů, měli byste místo dat zkusit přišít do zdrojového kódu následující testovací řádek: „ABC \ u0410 \ u0411 \ u0412“ a pokusit se o jeho výstup. Poté se podívejte, co máte:

    • Pokud vidíte „ABVABV“, kompilace zdrojů a výstup pro vás funguje správně.
    • Pokud místo prvních tří písmen vidíte „??? ABC“ (nebo jiné znaky než „ABC“), výstup funguje správně, ale kompilace zdrojů je špatná - s největší pravděpodobností klíč -encoding není specifikováno.
    • Pokud vidíte "??????" (nebo jiné symboly kromě „ABC“ místo druhých tří písmen), pak vám výstup nefunguje správně.

    Po nakonfigurování výstupu a kompilace již můžete snadno zjistit vstup. Po nastavení celého řetězce by měly být problémy pryč.

    O nástroji native2ascii

    Tento nástroj je součástí Sun JDK a je určen k převodu zdrojového kódu do formátu ASCII. Čte vstupní soubor pomocí zadaného kódování a zapisuje znaky ve formátu "\ uXXXX". Pokud zadáte přepínač -reverse, provede se zpětný převod. Tento program je velmi užitečný pro převod souborů zdrojů (.properties) nebo pro zpracování zdrojů, pokud máte podezření, že je lze kompilovat na počítačích s neruským regionálním nastavením.

    Pokud spustíte program bez parametrů, pracuje se standardním vstupem (stdin) a nezobrazí nápovědu ke klávesám jako jiné nástroje. To vede k tomu, že si mnozí ani neuvědomují, že je nutné specifikovat parametry (snad kromě těch, kteří v sobě našli sílu a odvahu nahlédnout do dokumentace :-). Mezitím tento nástroj pro správnou práci musíte minimálně určit použité kódování (pomocí klíče -encoding). Pokud se tak nestane, použije se výchozí kódování (file.encoding), které se může od očekávaného poněkud lišit. V důsledku toho, když jste obdrželi nesprávné kódy písmen (kvůli nesprávnému kódování), můžete strávit spoustu času hledáním chyb v naprosto správném kódu.

    O metodě převodu znaků

    Mnoho lidí používá tuto metodu nesprávně, pravděpodobně plně nerozumí její podstatě a omezením. Je navržen tak, aby obnovil správné kódy písmen, pokud byly nesprávně interpretovány. Podstata metody je jednoduchá: původní bajtové pole se obnoví z přijatých nesprávných znaků pomocí příslušné kódové stránky. Potom se z této řady bajtů pomocí již správné stránky získají normální znakové kódy. Příklad:

    Řetězec res = nový řetězec (src.getBytes ("ISO-8859-1"), "Cp1251");

    Při používání této techniky může být několik problémů. Například je k obnovení použita nesprávná stránka nebo se to může v některých situacích změnit. Dalším problémem může být, že některé stránky provádějí nejednoznačný převod bajtů<->char. Viz například popis chyby podle čísla.

    Tuto metodu byste proto měli používat pouze v tom nejextrémnějším případě, kdy nic jiného nepomáhá, a máte jasnou představu o tom, kde dochází k nesprávnému převodu znaků.

    Ruská písmena a MS JVM

    Není jasné, z jakých důvodů, ale chybí mu všechny soubory pro kódování ruských písmen, acrome Cp1251 (pravděpodobně se tímto způsobem pokusili zmenšit velikost distribuce). Pokud potřebujete další kódování, například Cp866, musíte do CLASSPATH přidat odpovídající třídy. Třídy z nejnovějších verzí Sun JDK navíc nesedí - Sun na dlouhou dobu měnil jejich strukturu, takže nejnovější verze tříd s Microsoftem nesedí (MS má strukturu z JDK 1.1.4). Na serveru Microsoft je v zásadě kompletní sada dalších kódování, ale existuje soubor o velikosti přibližně 3 metry a jejich server nepodporuje obnovení stahování :-). Podařilo se mi stáhnout tento soubor, přebalil jsem ho jarem, můžete si ho vzít odtud.

    Pokud píšete applet, který by měl fungovat pod MS JVM a potřebovali jste odněkud číst (například ze souboru na serveru) bajty v ruském kódování jiné než Cp1251 (například v Cp866), pak už nebudete být schopen používat standardní mechanismus kódování - apletům je zakázáno přidávat třídy do systémových balíčků, což je v tomto případě balíček sun.io. Existují dva způsoby - buď překódovat soubor na serveru na Cp1251 (nebo na UTF -8), nebo před převodem z bajtů na Unicode převést bajty z požadovaného kódování na Cp1251.

    Russifikace Javy pro Linux

    Hned řeknu - s Linuxem nepracuji a zde uvedené informace byly získány od čtenářů tohoto popisu. Pokud zjistíte nepřesnost nebo chcete přidat - napište mi.

    Při Cyrillizing JVM na Linuxu existují dva paralelní problémy:

    1. Problém s azbukou v komponentách GUI
    2. Problém se zadáváním azbuky z klávesnice (v X11)

    Problém s výběrem lze vyřešit tímto způsobem (tento algoritmus zaslal Artemy E. Kapitula):

    1. Do X11 nainstalujte normální písma Windows NT / 200 ttf. Doporučil bych Arial, Times New Roman, Courier New, Verdana a Tahoma - a je lepší je propojit ne přes server písem, ale jako adresář se soubory.
    2. Přidejte následující soubor font.properties.ru do adresáře $ JAVA_HOME / jre / lib

    Vstupní problém je vyřešen přibližně následujícím způsobem (tento algoritmus odeslal Michail Ivanov):

    Nastavení zadávání ruských písmen v následující konfiguraci:

    • Mandrake Linux 7.1
    • XFree86 3.3.6
    • IBM Java 1.3.0 (verze)

    Problém:

    IBM Java 1.3 neumožňuje zadávat ruská písmena (viditelná jako krokodýli), přestože jsou viditelná na štítcích a v nabídkách.

    pomocí XIM (-> xkb) v AWT. (to samo o sobě není špatné, jen je třeba s takovými věcmi zacházet opatrně + některým nástrojům xkb se to nelíbí).

    Konfigurace xkb (a locale (xkb bez locale NEFUNGUJE))

    Postup:

    1. locale je vystaven (někde jako / etc / profile nebo ~ / .bash_profile)
      export LANG = ru_RU.KOI8-R export LC_ALL = ru_RU.KOI8-R
    2. upravit (pokud již není provedeno) / etc / X11 / XF86Config. Sekce Klávesnice by měla obsahovat něco takového:
      XkbKeycodes "xfree86" XkbTypes "výchozí" XkbCompat "výchozí" XkbSymbols "ru" XkbGeometry "pc" XkbRules "xfree86" XkbModel "pc101" XkbLayout "ru" XkbOptions "grp: shift_toggle ci
      poznámka: toto nastavení xkb není kompatibilní s xrus (a dalšími, jako je kikbd), a proto se s nimi budete muset rozloučit.
    3. X jsou restartovány. Musíte zkontrolovat, zda vše funguje (jako ruská písmena v terminálu a aplikacích)
    4. font.properties.ru -> $ JAVA_HOME / jre / lib
    5. fonts.dir -> $ JAVA_HOME / jre / lib / fonts
    6. cd $ JAVA_HOME / jre / lib / fonts; rm fonts.scale; ln -s fonts.dir fonts.scale

    Nyní by ruská písmena měla být zadávána a zobrazována bez problémů.

Pokud si v popisu všimnete nepřesnosti nebo chcete přidat, napište mi o tom a v tomto seznamu se také objeví vaše jméno. :-)

Plná podpora směrnic .htaccess je přiložena ...

Obnovení domény 199-00 rub

Kódování je tabulka znaků, kde je každému písmenu abecedy (stejně jako číslům a speciálním znakům) přiřazeno jedinečné číslo - kód znaku.

Standardizována je pouze polovina stolu, tzv. ASCII kód ​​- prvních 128 znaků, které obsahují písmena latinské abecedy. A nikdy s nimi nejsou žádné problémy. Druhá polovina tabulky (a celkem je 256 znaků - podle počtu států, které může jeden bajt zabrat) je uvedena pod národními symboly a tato část je v každé zemi jiná. Ale pouze v Rusku dokázali vymyslet až 5 různých kódování. Termín „jiný“ znamená, že stejný symbol odpovídá jinému digitálnímu kódu. Tito. pokud nesprávně určíme kódování textu, pak bude naše pozornost věnována absolutně nečitelnému textu.

Kódování se objevilo historicky. Zavolalo se první široce používané ruské kódování KOI-8... Byl vynalezen, když byl systém UNIX přizpůsoben ruskému jazyku. To bylo v sedmdesátých letech - před příchodem osobních počítačů. A až dosud je to v systému UNIX považováno za hlavní kódování.

Poté se objevily první osobní počítače a začal vítězný pochod DOSu. Místo použití již vymyšleného kódování se Microsoft rozhodl vytvořit vlastní, nekompatibilní s čímkoli. Tak to vypadalo Kódování DOS(nebo 866 kódová stránka). Mimochodem, představil speciální znaky pro kreslení rámů, které bylo široce používáno v programech napsaných pod DOSem. Například ve stejném Norton Commander.

Počítače Macintosh vyvinuté souběžně s počítači kompatibilními s IBM. Navzdory skutečnosti, že jejich podíl v Rusku je velmi malý, přesto byla potřeba rusifikace a samozřejmě bylo vynalezeno další kódování - MAC.

Čas plynul a v roce 1990 Microsoft vynesl na světlo první úspěšné Verze Windows 3,0-3,11. A spolu s tím i podpora národních jazyků. A opět byl proveden stejný trik jako u DOSu. Z nějakého neznámého důvodu nepodporovali žádný z dříve existujících (stejně jako OS / 2, který přijal kódování DOS jako standard), ale navrhli nový Vyhrajte kódování(nebo kódová stránka 1251 ). De facto se v Rusku stal nejrozšířenějším.

A konečně pátá možnost kódování již není spojena s konkrétní společností, ale s pokusy o standardizaci kódování na úrovni celé planety. To provedla mezinárodní normalizační organizace ISO. A hádejte, co udělali s ruským jazykem? Místo toho, aby si cokoli z výše uvedeného spletli s „standardní ruštinou“, přišli s dalším (!) A nazvali to dlouhou nestravitelnou kombinací ISO-8859-5... Samozřejmě se také ukázalo, že je nekompatibilní s čímkoli. A v tuto chvíli se toto kódování prakticky nikde nepoužívá. Zdá se, že je používán pouze v databázi Oracle. Alespoň jsem nikdy neviděl text v tomto kódování. Všechny prohlížeče to však podporují.

Nyní pracujeme na vytvoření nového univerzálního kódování ( UNICODE), ve kterém se má vtěsnat všechny jazyky světa do jedné tabulky kódů. Pak určitě nebudou žádné problémy. Za tímto účelem byly pro každý znak přiděleny 2 bajty. Maximální počet znaků v tabulce se tedy rozšířil na 65 535. Stále však zbývá příliš mnoho času, než se všichni přepnou na UNICODE.


Zde trochu odbočíme a zvážíme meta tag - Content -Type pro holistické vnímání.

Metaznačky se používají k popisu vlastností dokumentu HTML a musí být obsaženy ve značce HEAD. Meta tagy jako NAME obsahují textové informace o dokumentu, jeho autorovi a některá doporučení pro vyhledávače. Například: Roboti, Popis, Klíčová slova, Autor, Copyright.

Meta tagy typu HTTP-EQUIV ovlivňují tvorbu hlavičky dokumentu a určují režim jeho zpracování.

Meta tag Content -Type - Odpovídá za specifikaci typu dokumentu a kódování znaků.

Metaznačku Content-Type je nutné používat pouze s přihlédnutím k některým nuancím:

    Nejprve musí kódování znaků textu odpovídat kódování uvedenému ve značce.

    Za druhé, server by neměl při zpracování požadavku prohlížeče měnit kódování textu.

    Za třetí, pokud server změní kódování textu, musí opravit nebo odebrat metaznačku Content-Type.

Nedodržení těchto požadavků může vést k následujícímu: webový server automaticky detekuje kódování požadavku klienta a předá překódovanou stránku webovému prohlížeči. Prohlížeč zase přečte dokument podle metaznačky Content-Type. A pokud se kódování neshodují, dokument lze přečíst až po sérii složitých manipulací. To platí zejména pro starší prohlížeče.

Pozornost! Značka Meta Content-Type se velmi často vkládá HTML generátory kód.

Nejběžnější typy kódování jsou:

    Windows -1251 - azbuka (Windows).

    KOI8-r-azbuka (KOI8-R)

    cp866 - cyrilice (DOS).

    Windows -1252 - západní Evropa (Windows).

    Windows -1250 - střední Evropa (Windows).

Určitě každý zná metaznačku -

PROTI tento materiál použité výňatky z článku z webu http://cherry-design.ru/

Nedávno vydané domény s PR a TIC:

Služba http://reg.ru - největší hosting a registrátor domén, vám umožňuje požádat o registraci názvu domény, který byl nedávno vydán předchozím administrátorem. Uvolněné domény mají často vysoké sazby TIC a PR a jejich pořízení může být zajímavé.

Vydané domény .RU c TIC:
Zdarma prémiové domény:

Množství informací: 7659 bytů

Historicky bylo v prvních počítačích přiděleno 7 bitů, aby představovaly tištěné znaky (kódující text). 2 7 = 128. Tato částka stačila na zakódování všech malých a velká písmena Latinská abeceda, deset čísel a různé znaky a závorky. To je přesně ta 7bitová tabulka ASCII znaky(Americký standardní kód pro výměnu informací), detailní informace které můžete získat pomocí příkazu man ascii operační systém Linux.

Když bylo nutné kódovat národní abecedy, 128 znaků nestačilo. Bylo rozhodnuto přejít na kódování pomocí 8 bitů (tj. Jednoho bajtu). V důsledku toho se počet znaků, které lze tímto způsobem zakódovat, rovnal 2 8 = 256. Symboly národních abeced se současně nacházely ve druhé polovině tabulky kódu, to znamená, že obsahovaly jednotku v nejvýznamnějším bitu bajtu přiděleného pro kódování znaku. Tak se objevila norma ISO 8859, obsahující mnoho kódování pro nejběžnější jazyky.

Mezi nimi byla jedna z prvních tabulek pro kódování ruských písmen - ISO 8859-5(použijte příkaz man iso_8859_1 k získání kódů pro ruská písmena v této tabulce).

Přenos úkolů textové informace po síti byli nuceni vyvinout další kódování ruských písmen, tzv Koi8-R(kód zobrazení informací je 8bitový, rusifikovaný). Zvažte situaci, kdy je dopis obsahující ruský text odeslán prostřednictvím e-mailem... Stávalo se, že v procesu cestování po sítích bylo písmeno zpracováno programem, který pracoval se 7bitovým kódováním a vynuloval osmý bit. V důsledku této transformace byl kód znaku zmenšen o 128, čímž se změnil na kód znaku latinské abecedy. Bylo potřeba zvýšit stabilitu přenášených textových informací na nulování 8 bitů.

Naštěstí značný počet cyrilských písmen má fonetické protějšky v latinské abecedě. Například Ф a F, P a R. Existuje několik písmen, která se shodují i ​​v obrysu. Uspořádání ruských písmen kódová tabulka takovým způsobem, že jejich kód převyšuje kód podobná latina na číslo 128 dosáhli toho, že ztráta 8. bitu proměnila text, ačkoliv se skládal z jedné latinské abecedy, ale rusky mluvícímu uživateli stále rozuměl.

Protože ze všech v té době rozšířených operačních systémů byly nejpohodlnější způsoby práce se sítí různé klony operačních Unixové systémy pak se toto kódování stalo de facto standardem v těchto systémech. To v Linuxu stále platí. A právě toto kódování se nejčastěji používá k výměně pošty a novinek na internetu.

Pak přišla éra osobní počítače a operační systém MS DOS. Jak se ukázalo, kódování Koi8-R pro ni nebylo vhodné (stejně jako ISO 8859-5), v její tabulce byla některá ruská písmena na těch místech, která řada programů předpokládala vyplněná pseudografiemi (vodorovné a svislé čáry, rohy atd.) .). atd.). Proto bylo vynalezeno další kódování azbuky, v jehož tabulce ruská písmena „proudila“ kolem grafických symbolů ze všech stran. Nazývá se toto kódování alternativní(alt), protože to byla alternativa k oficiální normě, kódování ISO-8859-5. Nespornou výhodou tohoto kódování je, že ruská písmena jsou v něm uspořádána v abecedním pořadí.

Po objevení Windows od Microsoftu se ukázalo, že z nějakého důvodu pro něj alternativní kódování není vhodné. Opětovné přesunutí ruských písmen do tabulky (byla příležitost - koneckonců pseudo -grafika ve Windows není vyžadována), dostali jsme kódování Windows 1251(Win-1251).

Počítačové technologie se ale neustále zlepšují a v současné době začíná stále větší počet programů podporovat standard Unicode, který umožňuje zakódovat téměř všechny jazyky a dialekty obyvatel Země.

V různých operačních systémech jsou tedy upřednostňována různá kódování. Aby bylo možné číst a upravovat text zadaný v jiném kódování, používají se ruské programy pro překódování textu. Nějaký textové editory obsahují vestavěné transkodéry, které vám umožňují číst text v různých kódováních (Word atd.). K převádění souborů použijeme v Linuxu řadu utilit, jejichž účel je jasný z názvu: alt2koi, win2koi, koi2win, alt2win, win2alt, koi2alt (odkud, kde je číslo 2 (dva) podobné v zvuk na předložku k, udávající směr). Tyto příkazy mají stejnou syntaxi: příkaz<входной_файл >výstupní soubor.

Příklad

Překódujme text zadaný v editoru Edit v prostředí MS DOS do kódování Koi8-R. Chcete -li to provést, spusťte příkaz

alt2koi file1.txt> filenew

Vzhledem k tomu, že kanály řádků jsou v systému MS DOS a Linux kódovány odlišně, doporučujeme také spustit příkaz „fromdos“:

fromdos filenew> file2.txt

Zpětný příkaz se nazývá „todos“ a má stejnou syntaxi.

Příklad

Pojďme seřadit soubor List.txt obsahující seznam příjmení a připravený v kódování Koi8-R v abecedním pořadí. Použijme příkaz sort, který třídí textový soubor vzestupně nebo sestupně podle znakových kódů. Pokud to použijete okamžitě, pak například dopis PROTI bude na konci seznamu, podobně jako odpovídající písmeno latinské abecedy PROTI... Pamatujeme-li, že v alternativním kódování jsou ruská písmena uspořádána přísně podle abecedy, provedeme řadu operací: překódovat text do alternativního kódování, seřadit jej a vrátit zpět do kódování Koi8-R. Pomocí příkazového potrubí dostaneme

koi2alt List.txt | třídit | alt2koi> List_Sort.txt

V moderních distribucích Linuxu je mnoho problémů spojených s lokalizace software... Obslužný program řazení nyní zejména zohledňuje zvláštnosti kódování Koi8-R a pro seřazení souboru podle abecedy stačí spustit příkaz

Kódování

Když jsem poprvé začal programovat v C, můj první program (kromě HelloWorld) byl program pro převod textových souborů z hlavního kódování GOST (pamatujete si tohle? :-) na alternativní. Bylo to v roce 1991. Od té doby se mnohé změnilo, ale bohužel tyto programy za posledních 10 let neztratily svůj význam. V různých kódováních již bylo nahromaděno příliš mnoho dat a je použito příliš mnoho programů, které mohou pracovat pouze s jedním. Existuje nejméně tucet různých kódování pro ruský jazyk, což činí problém ještě více matoucím.

Kde se všechna tato kódování vzala a k čemu jsou? Počítače ze své podstaty mohou pracovat pouze s čísly. Aby bylo možné ukládat písmena do paměti počítače, je nutné každému písmenu přiřadit určité číslo (přibližně stejný princip byl použit ještě předtím, než se objevily počítače - pamatujte si stejnou morseovku). Navíc je žádoucí menší číslo - čím méně binárních číslic je použito, tím efektivněji lze paměť využít. Tato korespondence mezi sadou znaků a čísel je ve skutečnosti kódováním. Touha zachránit paměť za každou cenu, stejně jako nejednotnost různých skupin počítačových vědců, vedla k současnému stavu věcí. Nyní je nejběžnější metodou kódování použít jeden bajt (8 bitů) pro jeden znak, který určuje celkový počet znaků ve 256. Sada prvních 128 znaků je standardizována (sada ASCII) a je stejná ve všech běžných kódováních (ta kódování, kde ještě není tak prakticky mimo provoz). Anglikánská písmena a interpunkční symboly jsou v tomto rozmezí, což určuje jejich úžasnou schopnost přežít v počítačových systémech :-). Jiné jazyky nejsou tak šťastné - všechny se musí schoulit ve zbývajících 128 číslech.

Unicode

Na konci osmdesátých let si mnozí uvědomili potřebu vytvořit jednotný standard pro kódování znaků, což vedlo ke vzniku Unicode. Unicode je pokus o opravu konkrétního čísla pro konkrétní znak jednou provždy. Je jasné, že 256 znaků se sem při vší touze nevejde. Poměrně dlouho se zdálo, že 2 bajty (65 536 znaků) by měly stačit. Ale ne - nejnovější verze standardu Unicode (3.1) již definuje 94 140 znaků. Pro takový počet znaků již pravděpodobně musíte použít 4 bajty (4294967296 znaků). Na chvíli možná dost ... :-)

Sada znaků Unicode obsahuje nejrůznější písmena se všemi druhy pomlček a pomlček, řecké, matematické, hieroglyfy, pseudografické symboly atd. Atd. Včetně oblíbených znaků cyrilice (rozsah hodnot je 0x0400-0x04ff ). Na této straně tedy neexistuje žádná diskriminace.

Pokud vás zajímají konkrétní kódy znaků, je vhodné k jejich zobrazení použít program „Character Map“ od WinNT. Například zde je azbuka:

Pokud máte jiný operační systém nebo vás zajímá oficiální výklad, pak úplné grafy najdete na oficiálním webu Unicode (http://www.unicode.org/charts/web.html).

Typy znaků a bajtů

Java má pro znaky samostatný datový typ char 2 bajty. To často způsobuje zmatek v myslích začátečníků (zvláště pokud dříve programovali v jiných jazycích, jako je C / C ++). Důvodem je, že většina ostatních jazyků používá ke zpracování znaků jednobajtové datové typy. Například v C / C ++ se char většinou používá jak pro zpracování znaků, tak pro zpracování bajtů - neexistuje žádné oddělení. Java má svůj vlastní typ pro bajty - typ bajtů. Char C na bázi tedy odpovídá bajtu Java a znak Java ze světa C je nejblíže typu wchar_t. Je nutné jasně oddělit pojmy postav a bajtů - v opačném případě je zaručeno nedorozumění a problémy.

Java používá standard kódování znaků Unicode téměř od svého vzniku. Funkce knihovny Java očekávají znaky Unicode v proměnných char. V zásadě tam samozřejmě můžete nacpat cokoli - čísla jsou čísla, procesor všechno vydrží, ale při jakémkoli zpracování budou funkce knihovny fungovat za předpokladu, že dostali kódování Unicode. Můžete tedy bezpečně předpokládat, že kódování znaků je pevné. Ale to je uvnitř JVM. Když jsou data čtena zvenčí nebo předávána zvenčí, mohou být reprezentována pouze jedním typem - typem bajtů. Všechny ostatní typy jsou vytvořeny z bajtů v závislosti na použitém formátu dat. Tady vstupuje do hry kódování - v Javě je to jen datový formát pro přenos znaků, který slouží k vytváření dat typu char. Pro každou kódovou stránku má knihovna 2 třídy převodu (ByteToChar a CharToByte). Tyto třídy jsou v balíčku sun.io. Pokud při převodu z char na byte nebyl nalezen žádný odpovídající znak, je nahrazen znakem?

Mimochodem, tyto soubory kódové stránky v některých raných verzích JDK 1.1 obsahují chyby, které způsobují chyby převodu nebo dokonce výjimky za běhu. Týká se to například kódování KOI8_R. Nejlepší je přitom změnit verzi na novější. Soudě podle popisu společnosti Sun byla většina těchto problémů vyřešena v JDK 1.1.6.

Před JDK 1.4 byla sada dostupných kódování určena pouze prodejcem JDK. Počínaje verzí 1.4 se objevilo nové API (balíček java.nio.charset), pomocí kterého si již můžete vytvořit vlastní kódování (například podporovat zřídka používané, ale pro vás strašně nutné).

Řetězcová třída

Ve většině případů Java používá k reprezentaci řetězců objekt typu java.lang.String. Toto je běžná třída, která interně ukládá řadu znaků (char) a která obsahuje mnoho užitečných metod pro manipulaci se znaky. Nejzajímavější jsou konstruktory s bajtovým polem jako prvním parametrem a metody getBytes (). Pomocí těchto metod můžete provádět převody z bajtových polí na řetězce a naopak. Aby bylo možné určit, které kódování použít současně, mají tyto metody řetězcový parametr, který nastavuje jeho název. Zde například můžete převést bajty z KOI-8 na Windows-1251:

// Data kódovaná KOI-8 byte koi8Data = ...; // Převod z KOI-8 na UnicodeŘetězec řetězce = nový řetězec (koi8Data, "KOI8_R"); // Převod z Unicode na Windows-1251 byte winData = string.getBytes ("Cp1251");

Seznam 8bitových kódování dostupných v moderních JDK a podpůrných ruských písmen naleznete níže v sekci.

Protože kódování je datový formát pro znaky, existují kromě známých 8bitových kódování v Javě také vícebajtová kódování na stejné úrovni. Patří sem UTF-8, UTF-16, Unicode atd. Například takto můžete získat bajty ve formátu UnicodeLittleUnmarked (16bitové kódování Unicode, nejprve nízký bajt, žádný znak pořadí bajtů):

// Převod z Unicode na Unicode byte data = string.getBytes ("UnicodeLittleUnmarked");

Je snadné udělat chybu s takovými převody - pokud kódování bajtových dat neodpovídá zadanému parametru při převodu z bajtu na char, pak překódování nebude provedeno správně. Někdy poté můžete vytáhnout správné znaky, ale častěji se část dat nenávratně ztratí.

Ve skutečném programu není vždy vhodné specifikovat kódovou stránku explicitně (i když je spolehlivější). Za tímto účelem bylo zavedeno výchozí kódování. Ve výchozím nastavení závisí na systému a jeho nastavení (kódování Cp1251 je přijato pro ruský Windows) a ve starých JDK je možné jej změnit nastavením vlastnosti souboru system.encoding. V JDK 1.3 změna tohoto nastavení někdy funguje, někdy ne. To je způsobeno následujícími příčinami: zpočátku se nastavení file.encoding nastaví podle regionálních nastavení počítače. Výchozí kódovací reference je při první konverzi interně zapamatována. V tomto případě se používá file.encoding, ale k tomuto převodu dochází ještě před použitím spouštěcích argumentů JVM (ve skutečnosti při jejich analýze). Ve skutečnosti Sun říká, že tato vlastnost odráží systémové kódování a neměla by být změněna na příkazovém řádku (viz například komentáře k BugID). V JDK 1.4 Beta 2 však změna tohoto nastavení opět začala mít účinek. Co je to, vědomá změna nebo vedlejší účinek, který může znovu zmizet - sluneční ovce dosud nedaly jasnou odpověď.

Toto kódování se používá, pokud název stránky není výslovně uveden. To by mělo být vždy pamatováno - Java se nebude pokoušet předpovídat kódování bajtů, které předáváte, aby vytvořil String (také nebude schopen číst vaše myšlenky na to :-). Pouze používá aktuální výchozí kódování. Protože toto nastavení je stejné pro všechny transformace, někdy můžete narazit na potíže.

Chcete -li převést z bajtů na znaky a naopak, použijte pouze těmito metodami. Ve většině případů nelze použít jednoduchý převod typu - kódování znaků nebude bráno v úvahu. Jednou z nejběžnějších chyb je například čtení dat po bajtech pomocí metody read () z InputStream a následné přenesení výsledné hodnoty na typ char:

InputStream je = ..; int b; StringBuffer sb = new StringBuffer (); while ((b = is.read ())! = - 1) (sb.append ((char) b); // <- так делать нельзя ) Řetězec s = sb.toString ();

Věnujte pozornost castingu - „(char) b“. Bajtové hodnoty se místo překódování jednoduše zkopírují do znaku (rozsah hodnot je 0-0xFF, nikoli ten, kde je umístěna azbuka). Toto kopírování odpovídá kódování ISO-8859-1 (které jedna ku jedné odpovídá prvním 256 hodnotám Unicode), což znamená, že můžeme předpokládat, že jej tento kód jednoduše používá (místo toho, ve kterém znaky v původní data jsou skutečně zakódována). Pokud se pokusíte zobrazit přijatou hodnotu, budou na obrazovce buď otázky, nebo krakozyably. Například při čtení řetězce „ABC“ v kódování Windows lze snadno zobrazit něco takového: „АÁВ“. Tento druh kódu často píší programátoři na Západě - funguje s anglickými písmeny a dobře. Oprava tohoto kódu je snadná - stačí vyměnit StringBuffer za ByteArrayOutputStream:

InputStream je = ..; int b; ByteArrayOutputStream baos = nový ByteArrayOutputStream (); while ((b = is.read ())! = - 1) (baos.write (b);) // Převod bajtů na řetězec pomocí výchozího kódováníŘetězec s = baos.toString (); // Pokud potřebujete konkrétní kódování, stačí ho zadat při volání toString (): // // s = baos.toString ("Cp1251");
Další informace o běžných chybách najdete v části.

8bitové kódování ruských písmen

Zde jsou hlavní 8bitová kódování ruských písmen, která se rozšířila:

Kromě hlavního jména lze použít i synonyma. Jejich sada se může v různých verzích JDK lišit. Zde je seznam z JDK 1.3.1:

  • Cp1251:
    • Windows-1251
  • Cp866:
    • IBM866
    • IBM-866
    • CP866
    • CSIBM866
  • KOI8_R:
    • KOI8-R
    • CSKOI8R
  • ISO8859_5:
    • ISO8859-5
    • ISO-8859-5
    • ISO_8859-5
    • ISO_8859-5: 1988
    • ISO-IR-144
    • 8859_5
    • cyrilice
    • CSISOLatinKyrilská
    • IBM915
    • IBM-915
    • Cp915

Synonyma navíc na rozdíl od hlavního jména nerozlišují velká a malá písmena - to je rys implementace.

Stojí za zmínku, že tato kódování nemusí být u některých JVM k dispozici. Můžete si například stáhnout dvě různé verze JRE z webu Sun - USA a International. V americké verzi existuje jen minimum-ISO-8859-1, ASCII, Cp1252, UTF8, UTF16 a několik variací dvoubajtového Unicode. Všechno ostatní je k dispozici pouze v mezinárodní verzi. Někdy kvůli tomu můžete při spuštění programu narazit na hrábě, i když nepotřebuje ruská písmena. Typická chyba, ke které dochází při tom:

Při inicializaci VM java / lang / ClassNotFoundException došlo k chybě: sun / io / ByteToCharCp1251

Vzniká, protože není těžké uhodnout, vzhledem k tomu, že se JVM na základě ruského regionálního nastavení pokouší nastavit výchozí kódování v Cp1251, ale protože třída takové podpory v americké verzi chybí, přirozeně se rozpadá.

Soubory a datové toky

Stejně jako jsou bajty koncepčně oddělené od znaků, Java rozlišuje mezi bajtovými toky a toky znaků. Práce s bajty je reprezentována třídami, které přímo nebo nepřímo dědí třídy InputStream nebo OutputStream (plus jedinečnou třídu RandomAccessFile). Práci se symboly reprezentuje sladký pár tříd Reader / Writer (a jejich potomci, samozřejmě).

Proudy bajtů se používají ke čtení / zápisu nepřevedených bajtů. Pokud víte, že bajty jsou pouze znaky v určitém kódování, můžete použít speciální třídy převaděčů InputStreamReader a OutputStreamWriter, abyste získali proud znaků a pracovali s ním přímo. To je obvykle užitečné pro soubory prostého textu nebo při práci s mnoha síťovými protokoly internetu. V tomto případě je kódování znaků zadáno v konstruktoru třídy převaděče. Příklad:

// Řetězec Unicode Řetězec řetězce = "..."; // Napište řetězec do textového souboru v kódování Cp866 PrintWriter pw = nový PrintWriter // třída s metodami pro zápis řetězců(nový OutputStreamWriter // převodník tříd(nový FileOutputStream ("file.txt"), "Cp866"); pw.println (řetězec); // zapište řádek do souboru pw.close ();

Pokud stream může obsahovat data v různých kódováních nebo jsou znaky smíchány s jinými binárními daty, pak je lepší číst a zapisovat bajtová pole a pro převod použít již zmíněné metody třídy String. Příklad:

// Řetězec Unicode Řetězec řetězce = "..."; // Napište řetězec do textového souboru ve dvou kódováních (Cp866 a Cp1251) OutputStream os = nový FileOutputStream ("file.txt"); // třída pro zápis bajtů do souboru // Napište řetězec v kódování Cp866 os.write (string.getBytes ("Cp866")); // Napište řetězec v kódování Cp1251 os.write (string.getBytes ("Cp1251")); os.close ();

Konzolu v Javě tradičně představují streamy, ale bohužel ne znaky, ale bajty. Faktem je, že proudy znaků se objevily pouze v JDK 1.1 (spolu s celým mechanismem kódování) a přístup k I / O konzoly byl navržen v JDK 1.0, což vedlo ke vzniku podivína v podobě třídy PrintStream. Tato třída se používá v proměnných System.out a System.err, které ve skutečnosti umožňují přístup k výstupu do konzoly. Podle všeho je to proud bajtů, ale se spoustou metod pro psaní řetězců. Když do něj napíšete řetězec, převede se na bajty pomocí výchozího kódování, což je v případě systému Windows obvykle nepřijatelné - výchozí kódování bude Cp1251 (Ansi) a pro okno konzoly je obvykle nutné použít Cp866 ( OEM). Tato chyba byla zaregistrována již v 97. roce (), ale zdá se, že sluneční ovečky nespěchají na její opravu. Protože neexistuje žádná metoda pro nastavení kódování v PrintStream, k vyřešení tohoto problému můžete standardní třídu nahradit vlastní metodou System.setOut () a System.setErr (). Například zde je obvyklý začátek v mých programech:

... public static void main (String args) ( // Nastavte výstup zpráv konzoly v požadovaném kódování try (String consoleEnc = System.getProperty ("console.encoding", "Cp866"); System.setOut (new CodepagePrintStream (System.out, consoleEnc)); System.setErr (new CodepagePrintStream (System.err, consoleEnc)); ) catch (UnsupportedEncodingException e) (System.out.println ("Nelze nastavit kódovou stránku konzoly:" + e);) ...

Zdroje třídy CodepagePrintStream najdete na tomto webu: CodepagePrintStream.java.

Pokud si formát dat vytváříte sami, doporučuji použít jedno z vícebajtových kódování. Nejpohodlnějším formátem je obvykle UTF8 - prvních 128 hodnot (ASCII) v něm je zakódováno v jednom bajtu, což často může výrazně snížit celkové množství dat (ne nadarmo se toto kódování bere jako základ v svět XML). UTF8 má však jednu nevýhodu - požadovaný počet bajtů závisí na kódu znaku. Pokud je to důležité, můžete použít jeden z dvoubajtových formátů Unicode (UnicodeBig nebo UnicodeLittle).

Databáze

Aby bylo možné správně číst znaky z databáze, obvykle stačí sdělit ovladači JDBC požadované kódování znaků v databázi. Jak přesně závisí na konkrétním ovladači. V dnešní době již mnoho řidičů toto nastavení na rozdíl od nedávné minulosti podporuje. Zde je několik příkladů, o kterých vím.

Most JDBC-ODBC

Toto je jeden z nejčastěji používaných ovladačů. Most od JDK 1.2 a starší lze snadno nakonfigurovat na požadované kódování. To se provádí přidáním další vlastnosti charSet do sady parametrů předaných k otevření připojení k základně. Výchozí hodnota je file.encoding. To se provádí takto:

// Navažte připojení

Ovladač Oracle 8.0.5 JDBC-OCI pro Linux

Při příjmu dat z databáze tento ovladač určuje „své“ kódování pomocí proměnné prostředí NLS_LANG. Pokud tato proměnná není nalezena, pak předpokládá, že kódování je ISO-8859-1. Jde o to, že NLS_LANG by měla být proměnná prostředí (nastavená příkazem set), nikoli vlastnost systému Java (jako file.encoding). V případě použití ovladače uvnitř servletového motoru Apache + Jserv lze proměnnou prostředí nastavit v souboru jserv.properties:

wrapper.env = NLS_LANG = American_America.CL8KOI8R
Informace o tom poslal Sergej Bezrukov, za což mu patří zvláštní poděkování.

Ovladač JDBC pro práci s DBF (zyh.sql.dbf.DBFDriver)

Tento řidič se teprve nedávno naučil pracovat s ruskými písmeny. I když hlásí getPropertyInfo (), že chápe vlastnost charSet, je to fikce (alespoň ve verzi z 30. 7. 2001). Ve skutečnosti můžete kódování přizpůsobit nastavením vlastnosti CODEPAGEID. Pro ruské znaky jsou k dispozici dvě hodnoty - „66“ pro Cp866 a „C9“ pro Cp1251. Příklad:

// Základní parametry připojení Vlastnosti connInfo = nové Properties (); connInfo.put ("CODEPAGEID", "66"); // Kódování Cp866 // Navažte připojení Připojení db = DriverManager.getConnection ("jdbc: DBF: / C: / MyDBFFiles", connInfo);
Pokud máte soubory DBF ve formátu FoxPro, pak mají svá vlastní specifika. Faktem je, že FoxPro ukládá do záhlaví souboru ID kódové stránky (bajt s ofsetem 0x1D), která byla použita k vytvoření DBF. Při otevírání tabulky používá ovladač hodnotu z hlavičky, nikoli parametr „CODEPAGEID“ (parametr se v tomto případě používá pouze při vytváření nových tabulek). Aby vše správně fungovalo, musí být soubor DBF vytvořen se správným kódováním - jinak budou problémy.

MySQL (org.gjt.mm.mysql.Driver)

S tímto ovladačem je vše také velmi jednoduché:

// Základní parametry připojení Vlastnosti connInfo = new Poperties (); connInfo.put ("uživatel", uživatel); connInfo.put ("heslo", heslo); connInfo.put ("useUnicode", "true"); connInfo.put ("characterEncoding", "KOI8_R"); Připojení conn = DriverManager.getConnection (dbURL, rekvizity);

InterBase (interbase.interclient.Driver)

U tohoto ovladače funguje parametr „charSet“:
// Základní parametry připojení Vlastnosti connInfo = nové Vlastnosti (); connInfo.put ("uživatel", uživatelské jméno); connInfo.put ("heslo", heslo); connInfo.put ("charSet", "Cp1251"); // Navažte připojení Připojení db = DriverManager.getConnection (dataurl, connInfo);

Při vytváření databáze a tabulek však nezapomeňte zadat kódování znaků. Pro ruský jazyk můžete použít hodnoty „UNICODE_FSS“ nebo „WIN1251“. Příklad:

VYTVOŘIT DATABÁZI „E: ProjectHoldingDataBaseHOLDING.GDB“ PAGE_SIZE 4096 SADA VÝCHOZÍCH ZNAKŮ UNICODE_FSS; VYTVOŘIT TABULKU RUSKÉ_Slovo („NAME1“ VARCHAR (40) SADA ZNAKŮ UNICODE_FSS NENÍ NULÁ, VARCHAR „NAME2“ (40) SADA ZNAKŮ WIN1251 NENÍ NULÁ, PRIMÁRNÍ KLÍČ („NAME1“));

Ve verzi 2.01 InterClient je chyba - třídy prostředků se zprávami pro ruský jazyk tam nejsou správně kompilovány. S největší pravděpodobností vývojáři při kompilaci jednoduše zapomněli zadat zdrojové kódování. Tuto chybu lze opravit dvěma způsoby:

  • Místo interclient.jar použijte interclient-core.jar. Současně prostě nebudou žádné ruské zdroje a ty anglické budou vyzvednuty automaticky.
  • Překompilovat soubory do normálního Unicode. Analýza souborů třídy je nevděčný úkol, takže je lepší použít JAD. Bohužel JAD, pokud narazí na znaky ze sady ISO-8859-1, je vydá v 8místném kódování, takže nebudete moci použít standardní kodér native2ascii-musíte si napsat vlastní (program Decode). Pokud se s těmito problémy nechcete trápit, můžete jednoduše vzít hotový soubor se zdroji (záplatovaná jar s ovladačem - interclient.jar, oddělené třídy zdrojů - interclient -rus.jar).

Ale i po vyladění ovladače JDBC na požadované kódování se v některých případech můžete dostat do potíží. Například při pokusu použít nádherné nové rolovací kurzory standardu JDBC 2 v můstku JDBC-ODBC z JDK 1.3.x rychle zjistíte, že tam ruská písmena jednoduše nefungují (metoda updateString ()).

S touto chybou je spojen malý příběh. Když jsem to poprvé objevil (pod JDK 1.3 rc2), zaregistroval jsem to u BugParade (). Když vyšla první beta verze JDK 1.3.1, byla tato chyba označena jako opravená. Potěšení, stáhl jsem si tuto beta verzi, spustil test - nefunguje. Napsal jsem o tom Slunným ovcím - v reakci na to mi napsali, že oprava bude zahrnuta v budoucích vydáních. Dobře, pomyslel jsem si, počkejme. Čas plynul, byla vydána verze 1.3.1 a poté beta 1.4. Nakonec jsem si udělal čas na kontrolu - už to nefunguje. Matka, matka, matka ... - ozvěna se ozývala obvyklým způsobem. Po rozzlobeném dopise Sunu zavedli novou chybu (), kterou dali indické větvi na roztrhání. Indiáni si pohrávali s kódem a řekli, že vše bylo opraveno v 1.4 beta3. Stáhl jsem si tuto verzi, spustil pod ní testovací případ, tady je výsledek -. Jak se ukázalo, beta3, která je distribuována na webu (build 84), není beta3, kde byla zahrnuta finální oprava (build 87). Nyní slibují, že oprava bude zahrnuta v 1.4 rc1 ... No, obecně, rozumíte :-)

Ruská písmena ve zdrojích programů Java

Jak již bylo zmíněno, program při provádění používá Unicode. Zdrojové soubory jsou psány v běžných editorech. Používám Far, pravděpodobně máte svého oblíbeného editora. Tyto editory ukládají soubory v 8bitovém formátu, což znamená, že uvažování podobné výše uvedenému platí i pro tyto soubory. Různé verze překladačů provádějí převod znaků mírně odlišně. Dřívější verze JDK 1.1.x používají nastavení file.encoding, které lze přepsat nestandardní volbou -J. V novějších (jak uvádí Denis Kokarev - od 1.1.4) byl zaveden další parametr -encoding, pomocí kterého můžete určit použité kódování. V kompilovaných třídách jsou řetězce zastoupeny ve formě Unicode (přesněji v upravené verzi formátu UTF8), takže to nejzajímavější se děje během kompilace. Proto je nejdůležitější zjistit, v jakém kódování jsou vaše zdrojové kódy a při kompilaci zadat správnou hodnotu. Ve výchozím nastavení bude použit stejný notoricky známý soubor. Kódování. Příklad volání kompilátoru:

Kromě použití tohoto nastavení existuje ještě jedna metoda - určit písmena ve formátu „uXXXX“, kde je uveden kód znaku. Tato metoda funguje se všemi verzemi a k ​​získání těchto kódů můžete použít standardní nástroj.

Pokud používáte jakékoli IDE, pak může mít své vlastní závady. Tato IDE často používají výchozí kódování pro čtení / ukládání zdrojů - věnujte proto pozornost regionálnímu nastavení vašeho OS. Kromě toho mohou existovat zjevné chyby - například docela dobrý CodeGuide v měřítku IDE špatně stráví velké ruské písmeno „T“. Vestavěný analyzátor kódu bere toto písmeno jako uvozovku, což vede k tomu, že správný kód je vnímán jako chybný. Můžete s tím bojovat (nahrazením písmene „T“ jeho kódem „u0422“), ale nepříjemné. Zjevně se někde uvnitř analyzátoru používá explicitní převod znaků na bajty (jako: byte b = (byte) c), takže místo kódu 0x0422 (kód písmene „T“) je kód 0x22 ( kód dvojité uvozovky).

JBuilder má další problém, ale ten souvisí spíše s ergonomií. Faktem je, že v JDK 1.3.0, pod kterým JBuilder standardně běží, existuje chyba (), kvůli které nově vytvořená okna GUI po aktivaci automaticky zahrnují rozložení klávesnice v závislosti na regionálním nastavení operačního systému. Tito. pokud máte ruské regionální nastavení, pak se bude neustále pokoušet přepnout na ruské rozložení, které překáží při psaní programů. Web JBuilder.ru má několik oprav, které mění aktuální národní prostředí v JVM na Locale.US, ale nejlepším způsobem je upgradovat na JDK 1.3.1, který tuto chybu opravil.

Začínající uživatelé JBuilderu se také mohou setkat s takovým problémem - ruská písmena jsou uložena jako kódy „uXXXX“. Abyste tomu zabránili, v dialogu Výchozí vlastnosti projektu na kartě Obecné v poli Kódování změňte Výchozí na Cp1251.

Pokud pro kompilaci nepoužíváte standardní javac, ale jiný překladač - věnujte pozornost tomu, jak provádí převod znaků. Některé verze kompilátoru IBM jikes například nechápou, že existují jiná kódování než ISO-8859-1 :-). V tomto ohledu existují verze záplatované, ale často je tam také sešité nějaké kódování - neexistuje takové pohodlí jako v javacu.

JavaDoc

Ke generování dokumentace HTML pro zdrojový kód se používá obslužný program javadoc, který je součástí standardní distribuce JDK. Chcete -li zadat kódování, má až 3 parametry:

  • -encoding - toto nastavení nastavuje zdrojové kódování. Výchozí hodnota je file.encoding.
  • -docencoding - toto nastavení určuje kódování generovaných souborů HTML. Výchozí hodnota je file.encoding.
  • -charset - toto nastavení určuje znakovou sadu, která bude zapsána do hlaviček generovaných souborů HTML ( ). Očividně by to mělo být stejné jako předchozí nastavení. Pokud toto nastavení vynecháte, metaznačka nebude přidána.

Ruská písmena v souborech vlastností

Metody načítání zdrojů se používají ke čtení souborů vlastností, které fungují určitým způsobem. Ve skutečnosti se ke čtení používá metoda Properties.load, která nepoužívá file.encoding (kódování ISO-8859-1 je ve zdrojích napevno zakódováno), takže jediným způsobem, jak určit ruská písmena, je použít formát „uXXXX“ a nástroj.

V JDK 1.1 a 1.2 metoda Properties.save funguje odlišně. Ve verzích 1.1 jednoduše zahodil vysoký bajt, takže fungoval správně pouze s anglickými písmeny. 1.2 provede reverzní převod na "uXXXX" tak, aby fungoval zrcadleně na metodu načítání.

Pokud vaše soubory vlastností nejsou načteny jako prostředky, ale jako běžné konfigurační soubory, a nejste s tímto chováním spokojeni, existuje pouze jedna cesta ven, napište svůj vlastní zavaděč.

Ruská písmena v servletech.

K čemu jsou tytéž servlety, myslím, že víš. Pokud ne, je nejlepší si nejprve přečíst dokumentaci. Zde jsou popsány pouze zvláštnosti práce s ruskými písmeny.

Jaké jsou tedy funkce? Když Servlet odešle klientovi odpověď, existují dva způsoby, jak tuto odpověď odeslat - prostřednictvím OutputStream (metoda getOutputStream ()) nebo prostřednictvím PrintWriter (metoda getWriter ()). V prvním případě píšete pole bajtů, takže platí výše uvedené metody zápisu do streamů. V případě PrintWriter používá nastavené kódování. V každém případě musíte správně zadat kódování použité při volání metody setContentType (), aby došlo ke správné konverzi znaků na straně serveru. Tuto směrnici je nutné provést před voláním getWriter () nebo před prvním zápisem do OutputStream. Příklad:

// Nastaví kódování odpovědi // Všimněte si, že některé motory to neumožňují // mezera mezi ';' a 'znakovou sadou' response.setContentType ("text / html; charset = UTF-8"); PrintWriter out = response.getWriter (); // Ladění výstupu názvu kódování ke kontrole out.println ("Kódování:" + response.getCharacterEncoding ()); ... out.close (); )

Jde o to dát klientovi odpovědi. Se vstupními parametry to bohužel není tak jednoduché. Vstupní parametry jsou kódovány bajtem prohlížeče podle typu MIME „application / x-www-form-urlencoded“. Jak řekl Alexey Mendelev, prohlížeče kódují ruská písmena pomocí aktuálně nastaveného kódování. A samozřejmě se o tom nic nehlásí. Proto například ve verzích JSDK od 2.0 do 2.2 toto není nijak kontrolováno a jaký druh kódování bude použit pro převod závisí na použitém enginu. Počínaje specifikací 2.3 bylo možné nastavit kódování pro javax.servlet.ServletRequest - metodu setCharacterEncoding (). Nejnovější verze Resin a Tomcat již tuto specifikaci podporují.

Pokud tedy máte štěstí a máte server s podporou Servlet 2.3, je vše celkem jednoduché:

public void doPost (požadavek HttpServletRequest, odpověď HttpServletResponse) vyvolá ServletException, IOException ( // Kódování zpráv request.setCharacterEncoding ("Cp1251"); Řetězcová hodnota = request.getParameter ("hodnota"); ...

Při aplikaci metody request.setCharacterEncoding () existuje jedna významná jemnost - musí být použita před první volání požadavku na data (například request.getParameter ()). Pokud použijete filtry, které zpracují požadavek, než dorazí do servletu, existuje nenulová šance, že jeden z filtrů může přečíst nějaký parametr z požadavku (například pro autorizaci) a request.setCharacterEncoding () v servletu nebude pracovat ...

Proto je ideologicky správnější napsat filtr, který nastaví kódování požadavku. Navíc musí být první v řetězci filtrů v souboru web.xml.

Příklad takového filtru:

import java.io. *; import java.util. *; import javax.servlet. *; import javax.servlet.http. *; veřejná třída CharsetFilter implementuje filtr (// kódování soukromého kódování řetězců; public void init (konfigurace FilterConfig) vyvolá ServletException ( // čtení z konfigurace encoding = config.getInitParameter ("requestEncoding"); // pokud není nainstalován, nainstalujte Cp1251 if (encoding == null) encoding = "Cp1251"; ) public void doFilter (ServletRequest request, ServletResponse response, FilterChain next) throws IOException, ServletException (request.setCharacterEncoding (encoding); next.doFilter (request, response);) public void destru () ())

A jeho konfigurace v web.xml:

Charsetový filtr CharsetFilter Charsetový filtr /*

Pokud nemáte štěstí a máte starší verzi, budete muset zvrátit, abyste dosáhli výsledku:

    Originální způsob práce s kódováním nabízí ruský Apache - je přesně popsáno jak.

  • FOP

    Balíček FOP je určen pro zpracování dokumentů podle standardu XSL FO (Formating Objects). Zejména vám umožňuje vytvářet dokumenty PDF na základě Dokumenty XML... Balíček FOP používá ve výchozím nastavení procesor Xalan XSLT spárovaný s Xerces k transformaci z nativního XML na FO. Chcete -li vytvořit konečný obrázek ve FOP, musíte připojit písma podporující ruská písmena. Pro verzi 0.20.1 to můžete provést takto:

    1. Zkopírujte soubory ttf ze systémového adresáře Windows do podadresáře conffonts (například v c: fop-0.20.1conffonts). Arial normal / normal, normal / bold, italic / normal, and italic / bold require arial.ttf, arialbd.ttf, ariali.ttf and arialbi.ttf files.
    2. Generujte soubory s popisem písma (například arial.xml). Chcete -li to provést, pro každé písmo musíte spustit příkaz (to je pro Arial normální / normální, vše v jednom řádku):
      java -cp .; c: fop-0.20.1uildfop.jar; c: fop-0.20.1libatik.jar; c: fop-0.20.1libxalan-2.0.0.jar; c: fop-0.20.1libxerces.jar; c: fop-0.20.1libjimi-1.0.jar org.apache.fop.fonts.apps.TTFReader fontsarial.ttf fontsarial.xml
    3. Ve FOP přidejte do conf / userconfig.xml popis písma s ruskými písmeny, například:
      Arial normal / bold, italic / normal a italic / bold se přidávají podobně.
    4. Při volání FOP z příkazový řádek po org.apache.fop.apps.Fop write -c c: fop -0.20.1confuserconfig.xml Pokud potřebujete použít FOP ze servletu, pak musíte v servletu za řádek
      Řidič řidič= nový ovladač ();
      přidat řádky:
      // Adresář písem (c: weblogicfonts) byl vytvořen pouze pro pohodlí.Řetězec userConfig = "fonts / userconfig.xml"; Soubor userConfigFile = nový soubor (userConfig); Options options = new Options (userConfigFile);
      Poté lze zadat umístění souborů ttf v souboru userconfig.xml relativně ke kořenovému adresáři aplikačního serveru, aniž by bylo nutné zadat absolutní cestu:
    5. Do souboru FO (nebo XML a XSL) před použitím písma napište:
      font-family = "Arial" font-weight = "bold" (Pokud používáte Arial tučně) font-style = "italic" (Pokud používáte Arial kurzívou)

    Tento algoritmus odeslal Alexey Tyurin, za což mu patří zvláštní poděkování.

    Pokud používáte prohlížeč zabudovaný do FOP, pak musíte vzít v úvahu jeho zvláštnosti. Zejména, ačkoli se předpokládá, že nápisy v něm jsou rusifikované, ve skutečnosti to bylo provedeno s chybou (ve verzi 0.19.0). K načtení štítků ze souborů prostředků používá balíček org.apache.fop.viewer.resources svůj vlastní zavaděč (třída org.apache.fop.viewer.LoadableProperties). Čtecí kódování je tam pevně fixováno (8859_1, jako v případě Properties.load ()), ale podpora pro typ "uXXXX" není implementována. Nahlásil jsem tuto chybu vývojářům, do svých plánů zahrnuli opravu.

    Mimo jiné existuje web věnovaný Russifikaci FOP (http://www.openmechanics.org/rusfop/) Zde najdete distribuční sadu FOP s již opravenými chybami a připojenými ruskými fonty.

    CORBA

    CORBA poskytuje typ, který odpovídá typu String Java. Toto je typ wstring. Všechno je v pořádku, ale některé servery CORBA nepodporují