Računalniki Windows Internet

Ruske črke v kodni tabeli Windows. Kodiranje v cirilici - rusko

Kodiranja

Ko sem prvič začel programirati v jeziku C, je bil moj prvi program (razen HelloWorld) program za kodiranje besedilne datoteke od glavnega kodiranja GOST (se spomnite tega? :-) do nadomestnega. Bilo je leta 1991. Od takrat se je veliko spremenilo, vendar na žalost takšni programi v zadnjih 10 letih niso izgubili pomembnosti. Preveč podatkov se je že zbralo v različnih kodiranjih in uporablja se preveč programov, ki lahko delujejo samo z enim. Za ruski jezik obstaja vsaj ducat različnih kodir, zaradi česar je težava še bolj zmedena.

Od kod prihajajo vsa ta kodiranja in čemu služijo? Računalniki po svoji naravi lahko delujejo samo s številkami. Za shranjevanje črk v pomnilnik računalnika je treba vsaki črki dodeliti določeno številko (približno isto načelo je bilo uporabljeno pred prihodom računalnikov - zapomnite si isto Morsejevo kodo). Poleg tega je število zaželeno manjše - manj ko je vključenih binarnih številk, učinkoviteje je mogoče uporabiti pomnilnik. To ujemanje med nizom znakov in številkami je pravzaprav kodiranje. Želja po varčevanju spomina za vsako ceno in neenotnost različnih skupin računalniških znanstvenikov sta privedla do trenutnega stanja. Najpogostejša metoda kodiranja je zdaj uporaba enega bajta (8 bitov) za en znak, ki določa skupno število znakov v 256. Niz prvih 128 znakov je standardiziran (niz ASCII) in je enak v vseh običajnih kodiranjih (tista kodiranja, kjer že praktično ni več v uporabi). Anglikanske črke in ločila so v tem razponu, kar določa njihovo neverjetno preživetje v računalniških sistemih :-). Drugi jeziki niso tako zadovoljni - vsi se morajo zbrati v preostalih 128 številkah.

Unicode

Konec osemdesetih let so mnogi spoznali potrebo po oblikovanju enotnega standarda za kodiranje znakov, kar je privedlo do nastanka Unicode. Unicode je poskus, da enkrat za vselej določi določeno številko za določen znak. Jasno je, da 256 znakov ne bo ustrezalo vsem željam. Dolgo se je zdelo, da bi morala biti dovolj 2 bajta (65536 znakov). Ampak ne - zadnja različica standarda Unicode (3.1) že opredeljuje 94.140 znakov. Za takšno število znakov morate verjetno že uporabiti 4 bajte (4294967296 znakov). Mogoče za nekaj časa dovolj ... :-)

V niz Znaki Unicode vključuje vse vrste črk z vsemi pomišljaji in papendyulki, grščino, matematiko, hieroglifi, psevdo-grafičnimi simboli itd. itd. Vključno z našimi najljubšimi cirilicami (razpon vrednosti je 0x0400-0x04ff). Na tej strani torej ni diskriminacije.

Če vas zanimajo posebne kode znakov, je za ogled priročno uporabiti program "Zemljevid znakov" iz WinNT. Tu je na primer obseg cirilice:

Če imate drug operacijski sistem ali vas zanima uradna razlaga, lahko celotne grafikone najdete na uradnem spletnem mestu Unicode (http://www.unicode.org/charts/web.html).

Vrste znakov in bajtov

Java ima ločen tip podatkov char 2 bajta za znake. To pogosto povzroča zmedo v glavah začetnikov (še posebej, če so že programirali v drugih jezikih, na primer v C / C ++). To je zato, ker večina drugih jezikov uporablja 1-bajtne podatkovne vrste za obdelavo znakov. Na primer, v C / C ++ se tip char v večini primerov uporablja tako za obdelavo znakov kot za obdelavo bajtov - ločitve ni. Java ima svoj tip bajtov - tip bajtov. Tako znamenje na osnovi C ustreza bajtu Java, znamenje Java iz sveta C pa je najbližje tipu wchar_t. Treba je jasno ločiti pojme znakov in bajtov - drugače so nesporazumi in težave zagotovljeni.

Java za kodiranje znakov uporablja že skoraj od svojega začetka Standard Unicode... Knjižnične funkcije Java pričakujejo prikaz znakov char, ki jih predstavlja Kode Unicode... Načeloma je seveda tam mogoče napolniti karkoli - številke so številke, procesor bo zdržal vse, toda za vsako obdelavo bodo knjižnične funkcije delovale ob predpostavki, da so bile Kodiranje Unicode... Tako lahko varno domnevate, da je kodiranje znakov fiksno. Ampak to je znotraj JVM. Ko se podatki berejo od zunaj ali posredujejo zunaj, jih lahko predstavlja le ena vrsta - vrsta bajtov. Vse druge vrste so zgrajene iz bajtov, odvisno od uporabljene oblike podatkov. Tu pridejo v poštev kodiranja - v Javi je to le podatkovni format za prenos znakov, ki se uporablja za oblikovanje podatkov tipa char. Za vsako kodno stran ima knjižnica 2 razreda pretvorbe (ByteToChar in CharToByte). Ti razredi so v paketu sun.io. Če pri pretvorbi iz znaka v bajt ni bil najden ustrezen znak, se nadomesti z znakom?

Mimogrede, te datoteke kodnih strani v nekaterih zgodnejših različicah JDK 1.1 vsebujejo hrošče, ki povzročajo napake pri pretvorbi ali celo izjeme med izvajanjem. To se na primer nanaša na kodiranje KOI8_R. Pri tem je najbolje, da nadgradite na novejšo različico. Po Sun -jevem opisu je bila večina teh težav rešena v JDK 1.1.6.

Pred JDK 1.4 je niz razpoložljivih kodiranj določil le prodajalec JDK. Začenši s 1.4 se je pojavil nov API (paket java.nio.charset), s katerim lahko že ustvarite lastno kodiranje (na primer podprete redko uporabljano, a za vas strašno potrebno).

Razredni niz

V večini primerov Java za predstavitev nizov uporablja objekt tipa java.lang.String. To je običajen razred, ki notranje shranjuje niz znakov (char) in vsebuje veliko uporabnih metod za upravljanje znakov. Najbolj zanimivi so konstruktorji z matriko bajtov kot prvim parametrom in metode getBytes (). S temi metodami lahko izvedete pretvorbe iz bajtnih nizov v nize in obratno. Za določitev, katero kodiranje naj se uporablja hkrati, imajo te metode parameter niza, ki nastavi njegovo ime. Tako lahko na primer pretvorite bajte iz KOI-8 v Windows-1251:

// Podatki kodirani KOI-8 bajt koi8Data = ...; // Pretvori iz KOI-8 v Unicode Niz niza = nov niz (koi8Data, "KOI8_R"); // Pretvarjanje iz Unicode v Windows-1251 bajt winData = string.getBytes ("Cp1251");

Seznam 8-bitnih kodir, ki so na voljo v sodobnih JDK-jih in podpirajo ruske črke, najdete spodaj, v razdelku.

Ker je kodiranje podatkovna oblika za znake, poleg znanih 8-bitnih kodiranj v Javi obstajajo enakovredna tudi večbajtna kodiranja. Ti vključujejo UTF-8, UTF-16, Unicode itd. Tako lahko na primer dobite bajte v formatu UnicodeLittleUnmarked (16-bitno kodiranje Unicode, najprej nizko bajt, brez znaka za zaporedje bajtov):

// Pretvarjanje iz Unicode v Unicode bajtni podatki = string.getBytes ("UnicodeLittleUnmarked");

Pri takšnih pretvorbah je enostavno narediti napako - če se kodiranje bajtnih podatkov ne ujema z določenim parametrom pri pretvorbi iz bajta v char, potem ponovno kodiranje ne bo izvedeno pravilno. Včasih lahko po tem izvlečete pravilne znake, vendar se večinoma del podatkov nepovratno izgubi.

V resničnem programu ni vedno priročno, da kodno stran izrecno navedete (čeprav je bolj zanesljiva). Za to je bilo uvedeno privzeto kodiranje. Privzeto je odvisno od sistema in njegovih nastavitev (za ruski Windows je sprejeto kodiranje Cp1251), v starih JDK -jih pa ga je mogoče spremeniti z nastavitvijo sistemske lastnosti file.encoding. V JDK 1.3 spreminjanje te nastavitve včasih deluje, včasih pa ne. To je posledica naslednjega: sprva je datotečno kodiranje nastavljeno glede na regionalne nastavitve računalnika. Privzeta referenca kodiranja se med prvo pretvorbo interno zapomni. V tem primeru se uporablja datoteka.encoding, vendar se ta pretvorba zgodi še pred uporabo zagonskih argumentov JVM (pravzaprav pri njihovi razčlenjevanju). Pravzaprav po Sun -ju ta lastnost odraža sistemsko kodiranje in je ne bi smeli spreminjati v ukazni vrstici (glej na primer komentarje na BugID) Vendar pa je v JDK 1.4 Beta 2 sprememba te nastavitve spet začela učinek. Kaj je to, zavestna sprememba ali stranski učinek, ki lahko spet izgine - Sončne ovce še niso dale jasnega odgovora.

To kodiranje se uporablja, če ime strani ni izrecno podano. To si morate zapomniti - Java ne bo poskušala napovedati kodiranja bajtov, ki jih posredujete za ustvarjanje niza (prav tako ne bo mogla prebrati vaših misli o tem :-). Uporablja samo trenutno privzeto kodiranje. Ker ta nastavitev je enaka za vse transformacije, včasih lahko naletite na težave.

Za pretvorbo iz bajtov v znake in obratno uporabite samo po teh metodah. V večini primerov preproste pretvorbe tipa ni mogoče uporabiti - kodiranje znakov ne bo upoštevano. Na primer, ena najpogostejših napak je branje podatkov po bajtih z uporabo metode read () iz InputStream, nato pa dobljeno vrednost oddate v tip char:

InputStream je = ..; int b; StringBuffer sb = nov StringBuffer (); medtem ko ((b = is.read ())! = - 1) (sb.append ((char) b); // <- так делать нельзя ) Niz s = sb.toString ();

Bodite pozorni na tipkanje - "(char) b". Vrednosti bajtov se preprosto kopirajo v char namesto ponovnega kodiranja (obseg vrednosti je 0-0xFF, ne tisti, kjer se nahaja cirilica). To kopiranje ustreza kodiranju ISO-8859-1 (ki ena na ena ustreza prvim 256 vrednostim Unicode), kar pomeni, da lahko domnevamo, da ga ta koda preprosto uporablja (namesto tistega, v katerem so znaki v izvirni podatki so dejansko kodirani). Če poskusite prikazati prejeto vrednost, se bodo na zaslonu pojavila vprašanja ali krakozyably. Na primer, ko berete niz "ABC" v kodiranju sistema Windows, se lahko zlahka prikaže nekaj takega: "АÁВ". Tovrstno kodo pogosto pišejo programerji na Zahodu - deluje z angleškimi črkami, in to je v redu. Popravljanje te kode je preprosto - preprosto morate zamenjati StringBuffer z ByteArrayOutputStream:

InputStream je = ..; int b; ByteArrayOutputStream baos = nov ByteArrayOutputStream (); medtem ko ((b = is.read ())! = - 1) (baos.write (b);) // Pretvorimo bajte v niz z uporabo privzetega kodiranja Niz s = baos.toString (); // Če potrebujete posebno kodiranje, ga pri klicu na toString () samo določite: // // s = baos.toString ("Cp1251");
Za več informacij o pogostih napakah glejte poglavje.

8-bitno kodiranje ruskih črk

Tu so glavna 8-bitna kodiranja ruskih črk, ki so postala zelo razširjena:

Poleg glavnega imena se lahko uporabljajo tudi sopomenke. Njihov nabor se lahko razlikuje v različnih različicah JDK. Tu je seznam iz 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
    • Cirilica
    • CSISOLatinCirilica
    • IBM915
    • IBM-915
    • Cp915

Poleg tega sopomenke, za razliko od glavnega imena, ne razlikujejo med velikimi in malimi črkami - to je značilnost izvedbe.

Omeniti velja, da ta kodiranja morda niso na voljo na nekaterih JVM -jih. Na primer, s spletnega mesta Sun lahko prenesete dve različici JRE - ameriško in mednarodno. V ameriški različici obstaja le minimum-ISO-8859-1, ASCII, Cp1252, UTF8, UTF16 in več različic dvobajtne Unicode. Vse ostalo je na voljo samo v mednarodni različici. Včasih lahko zaradi tega z zagonom programa naletite na grablje, tudi če ne potrebuje ruskih črk. Tipična napaka, ki se pojavi pri tem:

Med inicializacijo VM java / lang / ClassNotFoundException je prišlo do napake: sun / io / ByteToCharCp1251

Nastane, kot ni težko uganiti, zaradi dejstva, da JVM na podlagi ruskih regionalnih nastavitev poskuša nastaviti privzeto kodiranje v Cp1251, a ker razred takšne podpore v ameriški različici ni, se seveda prekine.

Datoteke in podatkovni tokovi

Tako kot so bajti konceptualno ločeni od znakov, Java razlikuje med bajtnimi tokovi in ​​tokovi znakov. Delo z bajti je predstavljeno z razredi, ki neposredno ali posredno podedujejo razrede InputStream ali OutputStream (plus edinstven razred RandomAccessFile). Delo s simboli predstavlja sladek par razredov Bralci / Pisatelji (in njihovi potomci, seveda).

Niz bajtov se uporablja za branje / pisanje nepreoblikovanih bajtov. Če veste, da bajti predstavljajo samo znake v določenem kodiranju, lahko uporabite posebne razrede pretvornikov InputStreamReader in OutputStreamWriter, da dobite tok znakov in neposredno delate z njimi. To je običajno uporabno za datoteke z navadnim besedilom ali pri delu z mnogimi internetnimi omrežnimi protokoli. V tem primeru je kodiranje znakov podano v konstruktorju razreda pretvornika. Primer:

// niz Unicode String string = "..."; // Zapišite niz v besedilno datoteko v kodiranju Cp866 PrintWriter pw = nov PrintWriter // razred z metodami za pisanje nizov(nov OutputStreamWriter // razred-pretvornik(nov FileOutputStream ("file.txt"), "Cp866"); pw.println (niz); // zapišemo vrstico v datoteko pw.close ();

Če lahko tok vsebuje podatke v različnih kodiranjih ali pa so znaki pomešani z drugimi binarnimi podatki, je bolje prebrati in zapisati bajtne matrike (bajte) in za pretvorbo uporabiti že omenjene metode razreda String. Primer:

// niz Unicode String string = "..."; // Zapišite niz v besedilno datoteko v dveh kodiranjih (Cp866 in Cp1251) OutputStream os = nov FileOutputStream ("file.txt"); // razred za zapisovanje bajtov v datoteko // Zapišite niz v kodiranje Cp866 os.write (string.getBytes ("Cp866")); // Zapišite niz v kodiranju Cp1251 os.write (string.getBytes ("Cp1251")); os.close ();

Konzola v Javi je tradicionalno predstavljena s tokovi, žal pa ne znaki, ampak bajti. Dejstvo je, da so se tokovi znakov pojavili le v JDK 1.1 (skupaj s celotnim mehanizmom kodiranja), dostop do konzolnih V / I pa je bil zasnovan v JDK 1.0, kar je privedlo do pojava čudaka v obliki razreda PrintStream. Ta razred se uporablja v spremenljivkah System.out in System.err, ki dejansko omogočata dostop do izhoda v konzolo. Vsekakor je to tok bajtov, vendar s kopico metod za pisanje nizov. Ko vanj vnesete niz, se s privzetim kodiranjem pretvori v bajte, kar je v primeru operacijskega sistema Windows običajno nesprejemljivo - privzeto kodiranje bo Cp1251 (Ansi), za okno konzole pa morate običajno uporabiti Cp866 ( OEM). Ta napaka je bila registrirana že v 97. letu (), a zdi se, da se Sun-ovac ne mudi popraviti. Ker v PrintStreamu ni načina za nastavitev kodiranja, lahko za rešitev te težave standardni razred zamenjate z lastnim z uporabo metod System.setOut () in System.setErr (). Tu je na primer običajen začetek mojih programov:

... javna statična void main (String args) ( // Nastavite izhod konzolnih sporočil v želeno kodiranje poskusite (String consoleEnc = System.getProperty ("console.encoding", "Cp866"); System.setOut (nov CodepagePrintStream (System.out, consoleEnc)); System.setErr (nov CodepagePrintStream (System.err, consoleEnc)); ) catch (UnsupportedEncodingException e) (System.out.println ("Ni mogoče nastaviti kodne strani konzole:" + e);) ...

Vire razreda CodepagePrintStream najdete na tem mestu: CodepagePrintStream.java.

Če sami oblikujete podatkovni format, vam priporočam, da uporabite eno od večbajtnih kodir. Najprimernejši format je običajno UTF8 - prvih 128 vrednosti (ASCII) v njem je kodiranih v enem bajtu, kar lahko pogosto znatno zmanjša skupno količino podatkov (ni zaman, da je to kodiranje osnova za svetu XML). Toda UTF8 ima eno pomanjkljivost - število potrebnih bajtov je odvisno od kode znakov. Kjer je to kritično, lahko uporabite enega od dvobajtnih formatov Unicode (UnicodeBig ali UnicodeLittle).

Baza podatkov

Za pravilno branje znakov iz baze podatkov je običajno dovolj, da gonilniku JDBC sporočite zahtevano kodiranje znakov v bazi podatkov. Kako natančno je odvisno od posameznega gonilnika. Dandanes to nastavitev podpira veliko voznikov, za razliko od nedavne preteklosti. Tukaj je nekaj primerov, ki jih poznam.

Most JDBC-ODBC

To je eden najpogosteje uporabljenih gonilnikov. Most iz JDK 1.2 in starejše je mogoče enostavno konfigurirati na želeno kodiranje. To naredimo tako, da v niz parametrov, ki so bili poslani za odpiranje povezave z bazo, dodamo dodatno lastnost charSet. Privzeto je file.encoding. To se naredi nekako takole:

// Vzpostavite povezavo

Oracle 8.0.5 JDBC-OCI gonilnik za Linux

Ko prejema podatke iz zbirke podatkov, ta gonilnik določi "njegovo" kodiranje s spremenljivko okolja NLS_LANG. Če te spremenljivke ni mogoče najti, predpostavlja, da je kodiranje ISO-8859-1. Trik je v tem, da mora biti NLS_LANG okoljska spremenljivka (nastavljena z ukazom set), ne pa sistemska lastnost Java (kot je file.encoding). Če se gonilnik uporablja znotraj motorja strežniških programčkov Apache + Jserv, lahko spremenljivko okolja nastavite v datoteki jserv.properties:

wrapper.env = NLS_LANG = American_America.CL8KOI8R
Podatke o tem je poslal Sergej Bezrukov, za kar se mu še posebej zahvaljuje.

Gonilnik JDBC za delo z DBF (zyh.sql.dbf.DBFDriver)

Ta voznik se je šele pred kratkim naučil delati z ruskimi črkami. Čeprav poroča z getPropertyInfo (), da razume lastnost charSet, je to fikcija (avtor vsaj v različici z dne 30. 7. 2001). V resnici lahko kodiranje prilagodite tako, da nastavite lastnost CODEPAGEID. Za ruske znake sta na voljo dve vrednosti - "66" za Cp866 in "C9" za Cp1251. Primer:

// Osnovni parametri povezave Lastnosti connInfo = nove lastnosti (); connInfo.put ("CODEPAGEID", "66"); // kodiranje Cp866 // Vzpostavite povezavo Povezava db = DriverManager.getConnection ("jdbc: DBF: / C: / MyDBFFiles", connInfo);
Če imate datoteke DBF v formatu FoxPro, potem imajo svoje posebnosti. Dejstvo je, da FoxPro v glavo datoteke shrani ID kodne strani (bajt z odmikom 0x1D), ki je bil uporabljen za ustvarjanje DBF. Pri odpiranju tabele gonilnik uporabi vrednost iz glave in ne parametra "CODEPAGEID" (parameter se v tem primeru uporablja le pri ustvarjanju novih tabel). V skladu s tem je za pravilno delovanje potrebno datoteko DBF ustvariti s pravilnim kodiranjem - sicer bodo težave.

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

S tem gonilnikom je vse tudi precej preprosto:

// Osnovni parametri povezave Lastnosti connInfo = nove lastnosti (); connInfo.put ("uporabnik", uporabnik); connInfo.put ("geslo", geslo); connInfo.put ("useUnicode", "true"); connInfo.put ("characterEncoding", "KOI8_R"); Povezava conn = DriverManager.getConnection (dbURL, rekviziti);

InterBase (interbase.interclient.Driver)

Za ta gonilnik deluje parameter "charSet":
// Osnovni parametri povezave Lastnosti connInfo = nove lastnosti (); connInfo.put ("uporabnik", uporabniško ime); connInfo.put ("geslo", geslo); connInfo.put ("charSet", "Cp1251"); // Vzpostavite povezavo Povezava db = DriverManager.getConnection (dataurl, connInfo);

Pri ustvarjanju baze podatkov in tabel pa ne pozabite navesti kodiranja znakov. Za ruski jezik lahko uporabite vrednosti "UNICODE_FSS" ali "WIN1251". Primer:

USTVARI BAZO PODATKOV "E: \ ProjectHolding \ DataBase \ HOLDING.GDB" PAGE_SIZE 4096 NASTAVITEV NASTAVLJENIH ZNAKOV UNICODE_FSS; USTVARI TABELO RUSSIAN_WORD ("NAME1" VARCHAR (40) CHARACTER SET UNICODE_FSS NOT NULL, "NAME2" VARCHAR (40) CHARACTER SET WIN1251 NOT NULL, PRIMARY KEY ("NAME1"));

V različici 2.01 InterClient je napaka - razredi virov s sporočili za ruski jezik tam niso pravilno sestavljeni. Najverjetneje so razvijalci pri sestavljanju preprosto pozabili navesti izvorno kodiranje. To napako lahko odpravite na dva načina:

  • Namesto interclient.jar uporabite interclient-core.jar. Hkrati ruskih virov preprosto ne bo, angleški pa bodo samodejno pobrani.
  • Znova prevedite datoteke v običajno Unicode. Razčlenjevanje datotek razreda je nehvaležna naloga, zato je bolje uporabiti JAD. Na žalost JAD, če naleti na znake iz nabora ISO-8859-1, jih prikaže v 8-mestnem kodiranju, zato ne boste mogli uporabljati standardnega kodirnika native2ascii-napisati morate svojega (program Decode). Če se ne želite ukvarjati s temi težavami, lahko vzamete že pripravljeno datoteko z viri (zakrpan kozarec z gonilnikom - interclient.jar, ločeni razredi virov - interclient -rus.jar).

Toda tudi če ste gonilnik JDBC nastavili na želeno kodiranje, lahko v nekaterih primerih naletite na težave. Ko na primer poskušate uporabiti čudovite nove drsne kazalce standarda JDBC 2 v mostu JDBC-ODBC iz JDK 1.3.x, hitro ugotovite, da ruske črke tam preprosto ne delujejo (metoda updateString ()).

S to napako je povezana majhna zgodba. Ko sem ga prvič odkril (pod JDK 1.3 rc2), sem ga registriral pri BugParade (). Ko je bila izdana prva beta različica JDK 1.3.1, je bila ta napaka označena kot odpravljena. Navdušen, prenesel sem to beta, opravil test - ne deluje. O tem sem pisal Sun -ovac - v odgovor so mi zapisali, da bo popravek vključen v prihodnje izdaje. V redu, sem si mislil, počakajmo. Čas je minil, izšla je izdaja 1.3.1 in nato beta 1.4. Končno sem si vzel čas za preverjanje - spet ne deluje. Mati, mati, mati ... - odmev je običajno odmeval. Po jeznem pismu Sun -u so uvedli novo napako (), ki so jo dali indijski veji, da jo raztrgajo. Indijanci so se poigravali s kodo in rekli, da je vse popravljeno v 1.4 beta3. Prenesel sem to različico, pod njo zagnal testni primer, tukaj je rezultat -. Izkazalo se je, da beta3, ki se distribuira na spletnem mestu (gradnja 84), ni beta3, kamor je bil vključen končni popravek (različica 87). Zdaj obljubljajo, da bo popravek vključen v 1.4 rc1 ... No, na splošno razumete :-)

Ruske črke v virih programov Java

Kot že omenjeno, program pri izvajanju uporablja Unicode. Izvorne datoteke so zapisane v običajnih urejevalnikih. Uporabljam Far, verjetno imate svojega najljubšega urejevalnika. Ti urejevalniki shranjujejo datoteke v 8-bitnem formatu, kar pomeni, da podobno sklepanje velja tudi za te datoteke. Različne različice prevajalnikov nekoliko drugače izvajajo pretvorbo znakov. Starejše različice JDK 1.1.x uporabljajo nastavitev file.encoding, ki jo je mogoče preglasiti z nestandardno možnostjo -J. V novejših (kot poroča Denis Kokarev - od 1.1.4) je bil uveden dodaten parameter kodiranja, s katerim lahko določite uporabljeno kodiranje. V prevedenih razredih so nizi predstavljeni v obliki Unicode (natančneje, v spremenjeni različici formata UTF8), zato se med kompilacijo zgodi najbolj zanimivo. Zato je najpomembnejše ugotoviti, v kakšnem kodiranju so vaše izvorne kode, in pri sestavljanju določite pravilno vrednost. Privzeto bo uporabljena ista razvpita koda file.encoding. Primer klicanja prevajalnika:

Poleg uporabe te nastavitve obstaja še ena metoda - določanje črk v formatu "\ uXXXX", kjer je označena koda znaka. Ta metoda deluje z vsemi različicami, za pridobitev teh kod pa lahko uporabite standardni pripomoček.

Če uporabljate kateri koli IDE, ima lahko svoje napake. Pogosto ti IDE uporabljajo privzeto kodiranje za branje / shranjevanje virov - zato bodite pozorni na regionalne nastavitve vašega OS. Poleg tega lahko pride do očitnih napak - na primer precej dober CodeGuide v merilu IDE ne prebavi dobro velike ruske črke "T". Vgrajeni analizator kode to črko jemlje kot dvojni narekovaj, kar vodi v dejstvo, da se pravilna koda dojema kot napačna. S tem se lahko borite (tako, da črko "T" zamenjate s kodo "\ u0422"), vendar neprijetno. Očitno se nekje znotraj razčlenjevalnika uporablja izrecna pretvorba znakov v bajte (na primer: bajt b = (bajt) c), zato je namesto kode 0x0422 (koda črke "T") koda 0x22 ( koda dvojnega narekovaja).

JBuilder ima še en problem, ki pa je bolj povezan z ergonomijo. Dejstvo je, da v JDK 1.3.0, pod katerim JBuilder privzeto deluje, obstaja napaka (), zaradi katere novo ustvarjena okna grafičnega vmesnika, ko so aktivirana, samodejno vključijo postavitev tipkovnice, odvisno od regionalnih nastavitev operacijskega sistema. Tisti. če imate ruske regionalne nastavitve, bo nenehno poskušal preiti na rusko postavitev, kar ovira pri pisanju programov. Spletno mesto JBuilder.ru ima nekaj popravkov, ki spremenijo trenutno področno nastavitev v JVM v Locale.US, vendar je najboljši način nadgradnja na JDK 1.3.1, ki je odpravil to napako.

Uporabniki novincev JBuilder se lahko srečajo tudi s takšno težavo - ruske črke se shranijo kot kode "\ uXXXX". Da bi se temu izognili, v pogovornem oknu Privzete lastnosti projekta, zavihek Splošno, v polju Kodiranje spremenite Privzeto v Cp1251.

Če za prevajanje uporabljate prevajalnik, ki ni standardni javac, bodite pozorni na to, kako izvaja pretvorbo znakov. Na primer, nekatere različice prevajalnika IBM jikes ne razumejo, da obstajajo kodiranja razen ISO-8859-1 :-). Za to so zakrpane različice, vendar je pogosto tudi tam šivano nekaj kodiranja - ni takšnega udobja kot v javac.

JavaDoc

Za ustvarjanje dokumentacije HTML za izvorno kodo se uporablja pripomoček javadoc, ki je vključen v standardno distribucijo JDK. Če želite določiti kodiranje, ima kar 3 parametre:

  • -kodiranje - ta nastavitev določa izvorno kodiranje. Privzeto je file.encoding.
  • -docencoding - ta nastavitev določa kodiranje ustvarjenih datotek HTML. Privzeto je file.encoding.
  • -charset - ta nastavitev določa kodiranje, ki bo zapisano v glave ustvarjenih datotek HTML ( ). Očitno bi moralo biti enako kot prejšnja nastavitev. Če je ta nastavitev izpuščena, metaoznaka ne bo dodana.

Ruske črke v datotekah lastnosti

Načini nalaganja virov se uporabljajo za branje datotek lastnosti, ki delujejo na poseben način. Pravzaprav se za branje uporablja metoda Properties.load, ki ne uporablja datoteke.encoding (izvorna koda je trdo kodirana s kodiranjem ISO-8859-1), zato je edini način za določitev ruskih črk uporaba "\ uXXXX" format in pripomoček.

Metoda Properties.save deluje drugače v JDK 1.1 in 1.2. V različici 1.1 je preprosto zavrgel visoki bajt, zato je pravilno deloval le z angleškimi črkami. 1.2 izvaja obratno pretvorbo v "\ uXXXX", zato deluje zrcalno na način nalaganja.

Če se datoteke z lastnostmi ne nalagajo kot viri, ampak kot navadne konfiguracijske datoteke in niste zadovoljni s tem vedenjem, obstaja le en izhod, napišite svoj nalagalnik.

Ruske črke v servletih.

No, čemu služijo ti isti servleti, mislim, da veste. Če ne, je najbolje, da najprej preberete dokumentacijo. Tu so opisane le posebnosti dela z ruskimi črkami.

Kakšne so torej lastnosti? Ko Servlet pošlje odgovor odjemalcu, obstajata dva načina za pošiljanje tega odgovora - prek OutputStream (metoda getOutputStream ()) ali prek PrintWriter (getWriter () metoda). V prvem primeru pišete matrike bajtov, zato veljajo zgornje metode pisanja v tokove. V primeru PrintWriter uporablja nastavljeno kodiranje. V vsakem primeru morate pravilno določiti kodiranje, ki se uporablja pri klicanju metode setContentType (), če želite pravilno pretvorbo znakov na strani strežnika. To direktivo je treba narediti pred klicem getWriter () ali pred prvim zapisom v OutputStream. Primer:

// Nastavimo kodiranje odziva // Upoštevajte, da nekateri motorji ne dovoljujejo // presledek med ";" in "charset" response.setContentType ("besedilo / html; charset = UTF-8"); PrintWriter out = response.getWriter (); // Odpravljanje napak imena kodiranja za preverjanje out.println ("Encoding:" + response.getCharacterEncoding ()); ... out.close (); )

Gre za podajanje odgovorov stranki. Žal z vhodnimi parametri ni tako enostavno. Vhodne parametre kodira bajt brskalnika v skladu z vrsto MIME "application / x-www-form-urlencoded". Kot je dejal Aleksej Mendelev, brskalniki kodirajo ruske črke s trenutno nastavljenim kodiranjem. In o tem seveda nič ne poročajo. V skladu s tem se na primer v različicah JSDK od 2.0 do 2.2 to nikakor ne preveri in kakšno kodiranje bo uporabljeno za pretvorbo, je odvisno od uporabljenega motorja. Od specifikacije 2.3 je bilo mogoče nastaviti kodiranje za javax.servlet.ServletRequest - metodo setCharacterEncoding (). Najnovejše različice Resin in Tomcat že podpirajo to specifikacijo.

Če imate srečo in imate strežnik s podporo Servlet 2.3, je vse precej preprosto:

public void doPost (zahteva HttpServletRequest, odgovor HttpServletResponse) vrže ServletException, IOException ( // Kodiranje sporočil request.setCharacterEncoding ("Cp1251"); Niz vrednost = request.getParameter ("vrednost"); ...

Obstaja ena pomembna subtilnost pri uporabi metode request.setCharacterEncoding () - uporabiti jo je treba prej prvi klic na zahtevo po podatkih (na primer request.getParameter ()). Če uporabljate filtre, ki obdelajo zahtevo, preden prispe v servlet, obstaja možnost, da ni nič, da se v enem od filtrov iz zahteve odčita kakšen parameter (na primer za avtorizacijo) in request.setCharacterEncoding () v servlet ne bo deloval ...

Zato je ideološko pravilneje napisati filter, ki nastavi kodiranje zahteve. Poleg tega mora biti prvi v verigi filtrov v web.xml.

Primer takega filtra:

uvoz java.io. *; uvoz java.util. *; uvoz javax.servlet. *; uvoz javax.servlet.http. *; javni razred CharsetFilter izvaja Filter (// kodiranje zasebnega kodiranja niza; javna void init (konfiguracija FilterConfig) vrže ServletException ( // branje iz konfiguracije encoding = config.getInitParameter ("requestEncoding"); // če ni nameščen, namestite Cp1251 if (encoding == null) encoding = "Cp1251"; ) public void doFilter (zahteva ServletRequest, odgovor ServletResponse, naslednji FilterChain) vrne IOException, ServletException (request.setCharacterEncoding (encoding); next.doFilter (request, response);) public void kill () ())

In njegova konfiguracija v web.xml:

Filter nabojev CharsetFilter Filter nabojev /*

Če nimate sreče in imate več stara različica- če želite doseči rezultat, morate sprevrniti:

    Izvirni način dela s kodiranjem ponuja ruski Apache - natančno je opisano, kako.

  • FOP

    Če program nikjer ne deluje, je težava le v njem in v vaših rokah. Pozorno preberi vse, kar je bilo napisano zgoraj, in poglej. Če se težava pokaže le v določenem okolju, je morda stvar v nastavitvah. Kje točno je odvisno od grafične knjižnice, ki jo uporabljate. Če AWT - lahko pomaga pravilna nastavitev datoteka font.properties.ru. Primer veljavne datoteke lahko vzamete iz Jave 2. Če te različice nimate, jo lahko prenesete s tega mesta: različica sistema Windows, različica Linuxa (glejte tudi spodaj). Ta datoteka določa pisave in kodne strani za uporabo. Če imate nameščeno rusko različico operacijskega sistema, samo dodajte to datoteko tja, kjer se nahaja datoteka font.properties. Če je to angleška različica, morate datoteko prepisati namesto font.properties ali pa dodatno spremeniti trenutne regionalne nastavitve v rusko. Včasih lahko nastavitev -Duser.language = ru deluje, pogosteje pa ne. Obstajajo približno enake težave kot pri datoteki.encoding - ali deluje ali ne, je odvisno od JDK (glej napako po številki).

    S knjižnico Swing je vse enostavnejše - v njej je vse narisano skozi podsistem Java2D. Oznake v standardnih pogovornih oknih (JOptionPane, JFileChooser, JColorChooser) je zelo enostavno pretvoriti v ruski jezik - samo ustvariti morate več datotek z viri. To sem že naredil, zato lahko vzamete končano datoteko in jo dodate v lib \ ext ali CLASSPATH. Edina težava, s katero sem se srečal, je, da v različicah JDK, ki se začnejo od 1.2 rc1 in 1.3 beta, ruske črke niso prikazane pod Win9x pri uporabi standardnih pisav (Arial, Courier New, Times New Roman itd.) Zaradi napake v Java2D. Napaka je precej nenavadna - pri standardnih pisavah so črkovne slike prikazane ne po kodah Unicode, ampak po tabeli Cp1251 ( Ansi kodiranje). Ta hrošč je registriran v BugParade pod številko. Swing privzeto uporablja pisave, navedene v datoteki font.properties.ru, zato jih je dovolj, da jih zamenjate z drugimi in prikažejo se ruske črke. Žal je niz delovnih pisav majhen - to so pisave Tahoma, Tahoma Bold in dva niza pisav iz distribucije JDK - Lucida Sans * in Lucida Typewriter * (primer datoteke font.properties.ru). Kako se te pisave razlikujejo od standardnih, mi ni jasno.

    Od različice 1.3rc1 je bila ta težava že odpravljena, zato morate samo posodobiti JDK. JDK 1.2 je že zelo zastarel, zato ga ne priporočam. Prav tako je treba opozoriti, da prvotna različica Win95 vsebuje pisave, ki ne podpirajo Unicode - v tem primeru lahko preprosto kopirate pisave iz Win98 ali WinNT.

    Tipične napake ali "kam je šla črka W?"

    Črka Sh.

    To vprašanje ("kam je šla črka W?") Pogosto si postavljajo začetniki Java programerji. Poglejmo, kam v resnici najpogosteje gre. :-)

    Tu je tipičen program v slogu HelloWorld:

    javni razred Test (public static void main (String args) (System.out.println ("ИЦУКЕНГШЩЗХХ");))
    prihranite daleč podano kodo v datoteko Test.java, prevedite ...
    C: \> javac Test.java
    in teči ...
    C: \> java Test YTsUKENG? ЩЗХЪ

    Kaj se je zgodilo? Kam je šla črka W? Trik je v tem, da je prišlo do medsebojnega nadomestila dveh napak. Urejevalnik besedila privzeto ustvari datoteko, kodirano z DOS (Cp866). Prevajalnik javac uporablja file.encoding za branje vira (razen če ni drugače določeno s ključem -encoding). In v Windows okolje z ruskim jezikom je privzeto kodiranje Cp1251. To je prva napaka. Posledično imajo simboli v prevedeni datoteki Test.class napačne kode. Druga napaka je, da se za izpis uporablja standardni PrintStream, ki uporablja tudi nastavitev iz file.encoding, vendar okno konzole Windows prikazuje znake z uporabo kodiranja DOS. Če bi bilo kodiranje Cp1251 medsebojno veljavno, ne bi prišlo do izgube podatkov. Toda znak W v Cp866 ima kodo 152, ki v Cp1251 ni opredeljena, zato se preslika v znak Unicode 0xFFFD. Pri pretvorbi nazaj iz znaka v bajt se nadomesti »?«.

    Podobno nadomestilo lahko naletite, če preberete znake iz besedilne datoteke z uporabo java.io.FileReader in jih nato prikažete na zaslonu z uporabo System.out.println (). Če je bila datoteka zapisana v kodiranju Cp866, bo izpis pravilno potekal, razen črke Š znova.

    Neposredna pretvorba bajtov<->char.

    Ta napaka je priljubljena med tujimi programerji Java. Podrobneje je obravnavano na začetku opisa. Če kdaj pogledate vire drugih ljudi, bodite vedno pozorni na izrecno pretvorbo tipov - (byte) ali (char). Na takšnih mestih so pogosto pokopane grablje.

    Algoritem za iskanje težav z ruskimi črkami

    Če ne veste, kje lahko v vašem programu pride do izgube ruskih črk, lahko poskusite z naslednjim testom. Vsak program se lahko obravnava kot procesor vhodnih podatkov. Ruske črke so enaki podatki, običajno gredo skozi tri stopnje obdelave: od nekje se preberejo v pomnilnik programa (vnos), obdelajo znotraj programa in prikažejo uporabniku (izhod). Če želite določiti lokacijo težav, namesto podatkov poskusite v izvorno kodo všiti naslednjo preskusno vrstico: "ABC \ u0410 \ u0411 \ u0412" in jo poskusiti prikazati. Po tem poglejte, kaj imate:

    • Če vidite "ABVABV", vam kompilacija virov in izhod deluje pravilno.
    • Če namesto prvih treh črk vidite "??? ABC" (ali kateri koli drug znak razen "ABC"), potem izhod deluje pravilno, vendar je sestava virov napačna - najverjetneje ključ za kodiranje ni določeno.
    • Če vidite "??????" (ali kateri koli drug simbol, razen "ABC" namesto drugih treh črk), potem izhod ne deluje pravilno.

    Ko ste konfigurirali izhod in kompilacijo, lahko že preprosto ugotovite vhod. Po nastavitvi celotne verige bi morale težave izginiti.

    O pripomočku native2ascii

    Ta pripomoček je del Sun JDK in je zasnovan za pretvorbo izvorne kode v format ASCII. Prebere vhodno datoteko z določenim kodiranjem in zapiše znake v formatu "\ uXXXX". Če podate obratno stikalo, se izvede obratna pretvorba. Ta program je zelo uporaben za pretvorbo datotek virov (.properties) ali za obdelavo virov, če sumite, da jih je mogoče sestaviti v računalnikih z neruskimi regionalnimi nastavitvami.

    Če program zaženete brez parametrov, deluje s standardnim vnosom (stdin) in ne prikazuje ključnega namiga, tako kot drugi pripomočki. To vodi v dejstvo, da se mnogi sploh ne zavedajo, da je treba določiti parametre (razen morda tistih, ki so našli moč in pogum, da pogledajo dokumentacijo :-). Medtem je ta pripomoček za pravilno delo morate vsaj določiti uporabljeno kodiranje (s ključem -encoding). Če tega ne storite, bo uporabljeno privzeto kodiranje (file.encoding), ki se lahko nekoliko razlikuje od pričakovanega. Posledično lahko po napačnih črkovnih kodah (zaradi napačnega kodiranja) porabite veliko časa za iskanje napak v popolnoma pravilni kodi.

    O načinu pretvorbe znakov

    Mnogi ljudje to metodo uporabljajo napačno, verjetno ne razumejo popolnoma njenega bistva in omejitev. Zasnovan je za obnovitev pravilnih črkovnih kod, če so bile napačno interpretirane. Bistvo metode je preprosto: prvotna matrika bajtov se obnovi iz prejetih napačnih znakov z uporabo ustrezne kodne strani. Nato iz tega niza bajtov z uporabo že pravilne strani dobimo običajne kode znakov. Primer:

    Niz res = nov Niz (src.getBytes ("ISO-8859-1"), "Cp1251");

    Pri uporabi te tehnike je lahko več težav. Na primer, za obnovitev se uporablja napačna stran ali pa se lahko v nekaterih situacijah spremeni. Druga težava je lahko v tem, da nekatere strani izvajajo dvoumno pretvorbo bajtov<->char. Glej na primer opis napake po številki.

    Zato bi morali to metodo uporabiti le v najbolj skrajnem primeru, ko nič drugega ne pomaga in imate jasno predstavo o tem, kje pride do napačne pretvorbe znakov.

    Ruske črke in MS JVM

    Iz katerih razlogov ni jasno, manjkajo pa vse datoteke za kodiranje ruskih črk, akrome Cp1251 (verjetno so na ta način poskušali zmanjšati velikost distribucije). Če potrebujete druga kodiranja, na primer Cp866, morate v CLASSPATH dodati ustrezne razrede. Poleg tega razredi iz najnovejših različic Sun JDK ne ustrezajo - Sun je dolgo časa spreminjal svojo strukturo, zato se najnovejše različice razredov ne ujemajo z Microsoftom (MS ima še vedno strukturo iz JDK 1.1.4). Na Microsoftovem strežniku načeloma obstaja celoten komplet dodatnih kodiranj, obstaja pa datoteka velikosti približno 3 metre, njihov strežnik pa ne podpira nadaljevanja prenosa :-). To datoteko mi je uspelo prenesti, zapakiral sem jo v jar, lahko jo vzamete od tukaj.

    Če pišete programček, ki bi moral delovati pod MS JVM, in ste morali od nekje (na primer iz datoteke na strežniku) prebrati bajte v ruskem kodiranju, ki ni Cp1251 (na primer v Cp866), potem ne boste več biti sposoben uporabljati standardni kodirni mehanizem - programčkom je prepovedano dodajanje razredov v sistemske pakete, kar je v tem primeru paket sun.io. Obstajata dva izhoda - bodisi, da datoteko na strežniku znova kodirate v Cp1251 (ali v UTF -8), ali pa pred pretvorbo iz bajtov v Unicode pretvorite bajte iz želenega kodiranja v Cp1251.

    Rusifikacija Jave za Linux

    Takoj bom rekel - ne delam z Linuxom in tukaj navedeni podatki so bili pridobljeni od bralcev tega opisa. Če ugotovite netočnost ali želite dodati - mi pišite.

    Pri kroženju JVM v Linuxu obstajata dve vzporedni težavi:

    1. Problem izpisa cirilice v komponentah grafičnega vmesnika
    2. Težava pri vnosu cirilice s tipkovnice (v X11)

    Problem umika je mogoče rešiti na ta način (ta algoritem je poslal Artemy E. Kapitula):

    1. Namestite običajne pisave Windows NT / 200 ttf v X11. Priporočam Arial, Times New Roman, Courier New, Verdana in Tahoma - in bolje je, da jih ne povežete prek strežnika pisav, ampak kot imenik z datotekami.
    2. V imenik $ JAVA_HOME / jre / lib dodajte naslednjo datoteko font.properties.ru

    Vhodni problem je rešen približno na naslednji način (ta algoritem je poslal Mihail Ivanov):

    Nastavitev vnosa ruskih črk v naslednji konfiguraciji:

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

    Težava:

    IBM Java 1.3 ne dovoljuje vnosa ruskih črk (vidnih kot krokodili), kljub temu, da so vidne na nalepkah in v menijih.

    z uporabo XIM (-> xkb) v AWT. (to samo po sebi ni slabo, le s takšnimi stvarmi je treba ravnati previdno + nekaterim orodjem xkb to ni všeč).

    Konfigurirajte xkb (in področna nastavitev (xkb brez področne nastavitve NE DELUJE))

    Postopek:

    1. locale je izpostavljen (nekje na primer / etc / profile ali ~ / .bash_profile)
      izvoz LANG = ru_RU.KOI8-R izvoz LC_ALL = ru_RU.KOI8-R
    2. uredi (če še ni narejeno) / etc / X11 / XF86Config. Razdelek Tipkovnica mora vsebovati nekaj takega:
      XkbKeycodes "xfree86" XkbTypes "privzeto" XkbCompat "privzeto" XkbSymbols "ru" XkbGeometry "pc" XkbRules "xfree86" XkbModel "pc101" XkbLayout "ru" XkbOptions "ohp# shift_tog preklop
      opomba: ta nastavitev xkb ni združljiva z xrus (in drugimi, kot je kikbd), zato se boste morali posloviti od njih.
    3. X se znova zaženejo. Preveriti morate, ali vse deluje (na primer ruske črke v terminalu in aplikacijah)
    4. font.properties.ru -> $ JAVA_HOME / jre / lib
    5. fonts.dir -> $ JAVA_HOME / jre / lib / pisave
    6. cd $ JAVA_HOME / jre / lib / pisave; rm pisave.razsežnost; ln -s pisave.dir pisave.razsežnost

    Zdaj je treba brez težav vnesti in prikazati ruske črke.

Če opazite netočnost v opisu ali želite dodati, mi pišite o tem in vaše ime bo prikazano tudi na tem seznamu. :-)

Priložena je popolna podpora direktivam .htaccess ...

Podaljšanje domene 199-00 rub

Kodiranje je tabela znakov, kjer je vsaki črki abecede (pa tudi številkam in posebnim znakom) dodeljena edinstvena številka - koda znakov.

Le polovica tabele je standardizirana, tako imenovana. Koda ASCII - prvih 128 znakov, ki vključujejo črke latinske abecede. In z njimi nikoli ni težav. Druga polovica tabele (v njej je skupaj 256 znakov - glede na število stanj, ki jih lahko sprejme en bajt) je pod Državni simboli in ta del je v vsaki državi drugačen. Toda le v Rusiji jim je uspelo izmisliti kar 5 različnih kodir. Izraz "drugačen" pomeni, da isti simbol ustreza drugačni digitalni kodi. Tisti. če napačno določimo kodiranje besedila, bo naša pozornost namenjena popolnoma neberljivemu besedilu.

Kodiranja so se pojavila zgodovinsko. Imenovalo se je prvo široko uporabljeno rusko kodiranje KOI-8... Izumili so ga, ko je bil sistem UNIX prilagojen ruskemu jeziku. To je bilo v sedemdesetih letih - pred prihodom osebnih računalnikov. In do zdaj v UNIX -u to velja za glavno kodiranje.

Takrat so se pojavili prvi osebni računalniki in začel se je zmagoslavni pohod DOS -a. Namesto da bi uporabil že izumljeno kodiranje, se je Microsoft odločil narediti svoje, nezdružljivo z ničemer. Tako se je pojavilo DOS kodiranje(oz 866 kodna stran). Mimogrede, uvedel je posebne znake za risanje okvirjev, kar se je pogosto uporabljalo v programih, napisanih pod DOS -om. Na primer v istem Norton Commanderju.

Računalniki Macintosh so se razvijali vzporedno z računalniki, združljivimi z IBM-om. Kljub temu, da je njihov delež v Rusiji zelo majhen, pa je bila potrebna rusifikacija in seveda je bilo izumljeno še eno kodiranje - MAC.

Čas je minil in leta 1990 je Microsoft predstavil prvega uspešnega Različica za Windows 3.0-3.11. Skupaj s tem pa tudi podpora nacionalnim jezikom. In spet je bil narejen isti trik kot pri DOS -u. Iz neznanega razloga niso podprli nobenega od prej obstoječih (tako kot OS / 2, ki je za standard sprejel kodiranje DOS), ampak so predlagali novo Win kodiranje(ali kodno stran 1251 ). Dejansko je postala najbolj razširjena v Rusiji.

In končno, peta možnost kodiranja ni več povezana z določenim podjetjem, ampak s poskusi standardizacije kodiranja na ravni celotnega planeta. To je storila ISO, mednarodna organizacija za standarde. In uganite, kaj so storili z ruskim jezikom? Namesto da bi karkoli od zgoraj naštetega zamenjali za "standardni ruski", so prišli do drugega (!) In ga poimenovali dolga neprebavljiva kombinacija ISO-8859-5... Seveda se je tudi izkazalo za nezdružljivo s čimer koli. In trenutno se to kodiranje praktično nikjer ne uporablja. Zdi se, da se uporablja samo v bazi podatkov Oracle. Vsaj besedila v tem kodiranju še nisem videl. Vendar pa ga podpirajo vsi brskalniki.

Zdaj delamo na ustvarjanju novega univerzalnega kodiranja ( UNICODE), v katerem naj bi vse jezike sveta strpali v eno kodno tabelo. Potem zagotovo ne bo težav. Za to sta bila za vsak znak dodeljena 2 bajta. Tako se je največje število znakov v tabeli povečalo na 65535. Vendar je še vedno preveč časa, preden vsi preidejo na UNICODE.


Tu se nekoliko oddaljimo in razmislimo o metaoznaki - Content -Type za celostno dojemanje.

Metaoznake se uporabljajo za opis lastnosti dokumenta HTML in morajo biti vsebovane v oznaki HEAD. Meta oznake, kot je NAME, vsebujejo besedilne podatke o dokumentu, njegovem avtorju in nekaj priporočil za iskalnike. Na primer: Roboti, Opis, Ključne besede, Avtor, Avtorske pravice.

Metaoznake tipa HTTP-EQUIV vplivajo na oblikovanje glave dokumenta in določajo način njegove obdelave.

Meta tag Content -Type - odgovoren za določanje vrste dokumenta in kodiranje znakov.

Metaoznako Content-Type je treba uporabiti le ob upoštevanju nekaterih odtenkov:

    Prvič, kodiranje znakov besedila se mora ujemati s kodiranjem, navedenim v oznaki.

    Drugič, strežnik ne sme spreminjati kodiranja besedila pri obdelavi zahteve brskalnika.

    Tretjič, če strežnik spremeni kodiranje besedila, mora popraviti ali odstraniti metaoznako Content-Type.

Neupoštevanje teh zahtev lahko povzroči naslednje: spletni strežnik bo samodejno zaznal kodiranje odjemalčeve zahteve in preusmerjeno stran dal spletnemu brskalniku. Brskalnik bo dokument prebral v skladu z metaoznako Content-Type. In če se kodiranja ne ujemajo, lahko dokument preberete šele po vrsti zapletenih manipulacij. To še posebej velja za starejše brskalnike.

Pozor! Meta oznaka vrste vsebine se zelo pogosto vstavi Generatorji HTML Koda.

Najpogostejše vrste kodiranja so:

    Windows -1251 - cirilica (Windows).

    KOI8-r-cirilica (KOI8-R)

    cp866 - cirilica (DOS).

    Windows -1252 - Zahodna Evropa (Windows).

    Windows -1250 - Srednja Evropa (Windows).

Zagotovo vsi poznajo metaoznako -

V ta material uporabljeni odlomki iz članka s spletnega mesta http://cherry-design.ru/

Nedavno izdane domene s PR in TIC:

Storitev http://reg.ru - največji registrator gostovanja in domen, vam omogoča, da se prijavite za registracijo imena domene, ki jo je pred kratkim izdal nekdanji skrbnik. Sproščene domene imajo pogosto visoke stopnje TIC in PR in jih je morda zanimivo kupiti.

Sproščene domene .RU c TIC:
Brezplačne premium domene:

Količina informacij: 7659 bajtov

V preteklosti je bilo za predstavitev natisnjenih znakov (kodiranje besedila) v prvih računalnikih dodeljenih 7 bitov. 2 7 = 128. Ta znesek je bil povsem dovolj za kodiranje vseh malih in velike črke Latinska abeceda, deset številk in različni znaki in oklepaji. To je točno 7-bitna tabela Znaki ASCII(Ameriški standardni kodeks za izmenjavo informacij), podrobne informacije ki ga lahko dobite z ukazom man ascii operacijski sistem Linux.

Ko je bilo treba kodirati nacionalne abecede, 128 znakov ni bilo dovolj. Odločeno je bilo, da preidemo na kodiranje z uporabo 8 bitov (to je en bajt). Posledično je število znakov, ki jih je mogoče kodirati na ta način, postalo enako 2 8 = 256. Hkrati so bili simboli nacionalnih abeced v drugi polovici kodne tabele, torej so vsebovali enoto v najpomembnejšem bitu bajta, dodeljenem za kodiranje znaka. Tako se je pojavil standard ISO 8859, ki vsebuje številne kodiranja za najpogostejše jezike.

Med njimi je bila ena prvih tabel za kodiranje ruskih črk - ISO 8859-5(uporabite ukaz man iso_8859_1, da dobite kode za ruske črke v tej tabeli).

Prenos nalog besedilne informacije po omrežju so bili prisiljeni razviti drugo kodiranje za ruske črke, imenovano Koi8-R(koda za prikaz informacij je 8-bitna, rusificirana). Razmislite o primeru, ko je pismo, ki vsebuje rusko besedilo, poslano prek E-naslov... Zgodilo se je, da je v procesu potovanja po omrežjih program obdelal črko, ki je delovala s 7-bitnim kodiranjem in ničlo osmi bit. Zaradi te preobrazbe se je koda znakov zmanjšala za 128 in se spremenila v kodo znakov latinske abecede. Stabilnost poslanih besedilnih informacij je bilo treba povečati na nič 8 bitov.

Na srečo ima veliko število cirilic črke v latinici. Na primer, F in F, P in R. Obstaja več črk, ki se ujemajo celo v orisu. Urejanje ruskih črk kodna miza tako, da njihova koda presega kodo podobna latinica na številko 128 so dosegli, da je izguba osmega bita spremenila besedilo, čeprav je bilo sestavljeno iz ene latinske abecede, vendar jo je rusko govoreči uporabnik še vedno razumel.

Ker so bili od vseh operacijskih sistemov, ki so bili takrat razširjeni, najprimernejša sredstva za delo z omrežjem različni kloni operacijskega sistema Unix sistemi potem je to kodiranje v teh sistemih dejansko postalo standard. To še vedno velja za Linux. Prav to kodiranje se najpogosteje uporablja za izmenjavo pošte in novic na internetu.

Potem je prišlo obdobje osebni računalniki in operacijski sistem MS DOS. Izkazalo se je, da kodiranje Koi8-R zanjo ni bilo primerno (tako kot ISO 8859-5), v njeni tabeli so bile nekatere ruske črke na tistih mestih, za katere so mnogi programi predvidevali, da so napolnjeni s psevdografijo (vodoravne in navpične črtice, vogali itd.) .) itd.). Zato je bilo izumljeno še eno cirilsko kodiranje, v tabeli katerega so ruske črke "tekle okoli" grafičnih simbolov z vseh strani. Imenuje se to kodiranje alternativa(alt), ker je bila alternativa uradnemu standardu kodiranje ISO-8859-5. Nesporna prednost tega kodiranja je, da so ruske črke v njem razporejene po abecednem vrstnem redu.

Po pojavu Microsoftovega sistema Windows se je izkazalo, da alternativno kodiranje iz nekega razloga zanj ni primerno. Ponovno premikanje ruskih črk v tabeli (bila je priložnost - navsezadnje psevdo -grafika v sistemu Windows ni potrebna) smo dobili kodiranje Windows 1251(Win-1251).

Toda računalniške tehnologije se nenehno izboljšujejo in trenutno vse več programov začenja podpirati standard Unicode, ki vam omogoča kodiranje skoraj vseh jezikov in narečij prebivalcev Zemlje.

Tako imajo v različnih operacijskih sistemih prednost različna kodiranja. Za branje in urejanje besedila, vpisanega v drugačnem kodiranju, se uporabljajo ruski programi za kodiranje besedila. Nekateri urejevalniki besedil vsebujejo vgrajene transkoderje, ki omogočajo branje besedila v različnih kodiranjih (Word itd.). Za pretvorbo datotek bomo v Linuxu uporabili številne pripomočke, katerih namen je razviden iz imena: alt2koi, win2koi, koi2win, alt2win, win2alt, koi2alt (od koder, kje je številka 2 (dve) podobna v zvok na predlog za, ki označuje smer). Ti ukazi imajo isto sintaksi: command<входной_файл >output_file.

Primer

Besedilo, vpisano v urejevalniku Edit v okolju MS DOS, kodirajmo v kodiranje Koi8-R. Če želite to narediti, zaženite ukaz

alt2koi file1.txt> filenew

Ker so viri vrstic v MS DOS in Linux različno kodirani, je priporočljivo tudi izvesti ukaz "fromdos":

fromdos filenew> file2.txt

Obratni ukaz se imenuje "todos" in ima isto skladnjo.

Primer

Razvrstimo datoteko List.txt, ki vsebuje seznam priimkov in pripravljeno v kodiranju Koi8-R po abecednem vrstnem redu. Uporabimo ukaz sort, ki razvrsti besedilno datoteko po naraščajočem ali padajočem vrstnem redu znakovnih kod. Če ga takoj uporabite, potem na primer pismo V bo na koncu seznama, podobno kot ustrezna črka latinske abecede V... Ne pozabimo, da so v alternativnem kodiranju ruske črke razporejene strogo po abecedi, bomo izvedli številne operacije: besedilo prekodiramo v alternativno kodiranje, ga razvrstimo in vrnemo v kodiranje Koi8-R. Z ukaznim kanalom dobimo

koi2alt List.txt | razvrsti | alt2koi> List_Sort.txt

V sodobnih distribucijah Linuxa je veliko težav povezanih z lokalizacija programsko opremo... Zlasti pripomoček za razvrščanje zdaj upošteva posebnosti kodiranja Koi8-R in če želite datoteko razvrstiti po abecednem vrstnem redu, preprosto zaženite ukaz

Kodiranja

Ko sem prvič začel programirati v jeziku C, je bil moj prvi program (razen HelloWorld) program za pretvorbo besedilnih datotek iz glavnega kodiranja GOST (se spomnite tega? :-) v alternativnega. Bilo je leta 1991. Od takrat se je veliko spremenilo, vendar na žalost takšni programi v zadnjih 10 letih niso izgubili pomembnosti. Preveč podatkov se je že zbralo v različnih kodiranjih in uporablja se preveč programov, ki lahko delujejo samo z enim. Za ruski jezik obstaja vsaj ducat različnih kodir, zaradi česar je težava še bolj zmedena.

Od kod prihajajo vsa ta kodiranja in čemu služijo? Računalniki po svoji naravi lahko delujejo samo s številkami. Za shranjevanje črk v pomnilnik računalnika je treba vsaki črki dodeliti določeno številko (približno isto načelo je bilo uporabljeno pred prihodom računalnikov - zapomnite si isto Morsejevo kodo). Poleg tega je število zaželeno manjše - manj ko je vključenih binarnih številk, učinkoviteje je mogoče uporabiti pomnilnik. To ujemanje med nizom znakov in številkami je pravzaprav kodiranje. Želja po varčevanju spomina za vsako ceno in neenotnost različnih skupin računalniških znanstvenikov sta privedla do trenutnega stanja. Najpogostejša metoda kodiranja je zdaj uporaba enega bajta (8 bitov) za en znak, ki določa skupno število znakov v 256. Niz prvih 128 znakov je standardiziran (niz ASCII) in je enak v vseh običajnih kodiranjih (tista kodiranja, kjer že praktično ni več v uporabi). Anglikanske črke in ločila so v tem razponu, kar določa njihovo neverjetno preživetje v računalniških sistemih :-). Drugi jeziki niso tako zadovoljni - vsi se morajo zbrati v preostalih 128 številkah.

Unicode

Konec osemdesetih let so mnogi spoznali potrebo po oblikovanju enotnega standarda za kodiranje znakov, kar je privedlo do nastanka Unicode. Unicode je poskus, da enkrat za vselej določi določeno številko za določen znak. Jasno je, da 256 znakov ne bo ustrezalo vsem željam. Dolgo se je zdelo, da bi morala biti dovolj 2 bajta (65536 znakov). Ampak ne - zadnja različica standarda Unicode (3.1) že opredeljuje 94.140 znakov. Za takšno število znakov morate verjetno že uporabiti 4 bajte (4294967296 znakov). Mogoče za nekaj časa dovolj ... :-)

Niz znakov Unicode vključuje vse vrste črk z vsemi pomišljaji in papendyulki, grškimi, matematičnimi, hieroglifi, psevdo grafičnimi simboli itd. . Na tej strani torej ni diskriminacije.

Če vas zanimajo posebne kode znakov, je za ogled priročno uporabiti program "Zemljevid znakov" iz WinNT. Tu je na primer obseg cirilice:

Če imate drug operacijski sistem ali vas zanima uradna razlaga, lahko celotne grafikone najdete na uradnem spletnem mestu Unicode (http://www.unicode.org/charts/web.html).

Vrste znakov in bajtov

Java ima ločen tip podatkov char 2 bajta za znake. To pogosto povzroča zmedo v glavah začetnikov (še posebej, če so že programirali v drugih jezikih, na primer v C / C ++). To je zato, ker večina drugih jezikov uporablja 1-bajtne podatkovne vrste za obdelavo znakov. Na primer, v C / C ++ se tip char v večini primerov uporablja tako za obdelavo znakov kot za obdelavo bajtov - ločitve ni. Java ima svoj tip bajtov - tip bajtov. Tako znamenje na osnovi C ustreza bajtu Java, znamenje Java iz sveta C pa je najbližje tipu wchar_t. Treba je jasno ločiti pojme znakov in bajtov - drugače so nesporazumi in težave zagotovljeni.

Java že od svojega začetka uporablja standard Unicode za kodiranje znakov. Knjižnične funkcije Java pričakujejo, da bodo v spremenljivkah char videli znake Unicode. Načeloma je seveda tam mogoče napolniti karkoli - številke so številke, procesor bo zdržal vse, toda za vsako obdelavo bodo knjižnične funkcije delovale ob predpostavki, da so dobile kodiranje Unicode. Tako lahko varno domnevate, da je kodiranje znakov fiksno. Ampak to je znotraj JVM. Ko se podatki berejo od zunaj ali posredujejo zunaj, jih lahko predstavlja le ena vrsta - vrsta bajtov. Vse druge vrste so zgrajene iz bajtov, odvisno od uporabljene oblike podatkov. Tu pridejo v poštev kodiranja - v Javi je to le podatkovni format za prenos znakov, ki se uporablja za oblikovanje podatkov tipa char. Za vsako kodno stran ima knjižnica 2 razreda pretvorbe (ByteToChar in CharToByte). Ti razredi so v paketu sun.io. Če pri pretvorbi iz znaka v bajt ni bil najden ustrezen znak, se nadomesti z znakom?

Mimogrede, te datoteke kodnih strani v nekaterih zgodnejših različicah JDK 1.1 vsebujejo hrošče, ki povzročajo napake pri pretvorbi ali celo izjeme med izvajanjem. To se na primer nanaša na kodiranje KOI8_R. Pri tem je najbolje, da nadgradite na novejšo različico. Po Sun -jevem opisu je bila večina teh težav rešena v JDK 1.1.6.

Pred JDK 1.4 je niz razpoložljivih kodiranj določil le prodajalec JDK. Začenši s 1.4 se je pojavil nov API (paket java.nio.charset), s katerim lahko že ustvarite lastno kodiranje (na primer podprete redko uporabljano, a za vas strašno potrebno).

Razredni niz

V večini primerov Java za predstavitev nizov uporablja objekt tipa java.lang.String. To je običajen razred, ki notranje shranjuje niz znakov (char) in vsebuje veliko uporabnih metod za upravljanje znakov. Najbolj zanimivi so konstruktorji z matriko bajtov kot prvim parametrom in metode getBytes (). S temi metodami lahko izvedete pretvorbe iz bajtnih nizov v nize in obratno. Za določitev, katero kodiranje naj se uporablja hkrati, imajo te metode parameter niza, ki nastavi njegovo ime. Tako lahko na primer pretvorite bajte iz KOI-8 v Windows-1251:

// Podatki kodirani KOI-8 bajt koi8Data = ...; // Pretvori iz KOI-8 v Unicode Niz niza = nov niz (koi8Data, "KOI8_R"); // Pretvarjanje iz Unicode v Windows-1251 bajt winData = string.getBytes ("Cp1251");

Seznam 8-bitnih kodir, ki so na voljo v sodobnih JDK-jih in podpirajo ruske črke, najdete spodaj, v razdelku.

Ker je kodiranje podatkovna oblika za znake, poleg znanih 8-bitnih kodiranj v Javi obstajajo enakovredna tudi večbajtna kodiranja. Ti vključujejo UTF-8, UTF-16, Unicode itd. Tako lahko na primer dobite bajte v formatu UnicodeLittleUnmarked (16-bitno kodiranje Unicode, najprej nizko bajt, brez znaka za zaporedje bajtov):

// Pretvarjanje iz Unicode v Unicode bajtni podatki = string.getBytes ("UnicodeLittleUnmarked");

Pri takšnih pretvorbah je enostavno narediti napako - če se kodiranje bajtnih podatkov ne ujema z določenim parametrom pri pretvorbi iz bajta v char, potem ponovno kodiranje ne bo izvedeno pravilno. Včasih lahko po tem izvlečete pravilne znake, vendar se večinoma del podatkov nepovratno izgubi.

V resničnem programu ni vedno priročno, da kodno stran izrecno navedete (čeprav je bolj zanesljiva). Za to je bilo uvedeno privzeto kodiranje. Privzeto je odvisno od sistema in njegovih nastavitev (za ruski Windows je sprejeto kodiranje Cp1251), v starih JDK -jih pa ga je mogoče spremeniti z nastavitvijo sistemske lastnosti file.encoding. V JDK 1.3 spreminjanje te nastavitve včasih deluje, včasih pa ne. To je posledica naslednjega: sprva je datotečno kodiranje nastavljeno glede na regionalne nastavitve računalnika. Privzeta referenca kodiranja se med prvo pretvorbo interno zapomni. V tem primeru se uporablja datoteka.encoding, vendar se ta pretvorba zgodi še pred uporabo zagonskih argumentov JVM (pravzaprav pri njihovi razčlenjevanju). Pravzaprav po Sun -ju ta lastnost odraža sistemsko kodiranje in je ne bi smeli spreminjati v ukazni vrstici (glej na primer komentarje na BugID) Vendar pa je v JDK 1.4 Beta 2 sprememba te nastavitve spet začela učinek. Kaj je to, zavestna sprememba ali stranski učinek, ki lahko spet izgine - Sončne ovce še niso dale jasnega odgovora.

To kodiranje se uporablja, če ime strani ni izrecno podano. To si morate zapomniti - Java ne bo poskušala napovedati kodiranja bajtov, ki jih posredujete za ustvarjanje niza (prav tako ne bo mogla prebrati vaših misli o tem :-). Uporablja samo trenutno privzeto kodiranje. Ker ta nastavitev je enaka za vse transformacije, včasih lahko naletite na težave.

Za pretvorbo iz bajtov v znake in obratno uporabite samo po teh metodah. V večini primerov preproste pretvorbe tipa ni mogoče uporabiti - kodiranje znakov ne bo upoštevano. Na primer, ena najpogostejših napak je branje podatkov po bajtih z uporabo metode read () iz InputStream, nato pa dobljeno vrednost oddate v tip char:

InputStream je = ..; int b; StringBuffer sb = nov StringBuffer (); medtem ko ((b = is.read ())! = - 1) (sb.append ((char) b); // <- так делать нельзя ) Niz s = sb.toString ();

Bodite pozorni na tipkanje - "(char) b". Vrednosti bajtov se preprosto kopirajo v char namesto ponovnega kodiranja (obseg vrednosti je 0-0xFF, ne tisti, kjer se nahaja cirilica). To kopiranje ustreza kodiranju ISO-8859-1 (ki ena na ena ustreza prvim 256 vrednostim Unicode), kar pomeni, da lahko domnevamo, da ga ta koda preprosto uporablja (namesto tistega, v katerem so znaki v izvirni podatki so dejansko kodirani). Če poskusite prikazati prejeto vrednost, se bodo na zaslonu pojavila vprašanja ali krakozyably. Na primer, ko berete niz "ABC" v kodiranju sistema Windows, se lahko zlahka prikaže nekaj takega: "АÁВ". Tovrstno kodo pogosto pišejo programerji na Zahodu - deluje z angleškimi črkami, in to je v redu. Popravljanje te kode je preprosto - preprosto morate zamenjati StringBuffer z ByteArrayOutputStream:

InputStream je = ..; int b; ByteArrayOutputStream baos = nov ByteArrayOutputStream (); medtem ko ((b = is.read ())! = - 1) (baos.write (b);) // Pretvorimo bajte v niz z uporabo privzetega kodiranja Niz s = baos.toString (); // Če potrebujete posebno kodiranje, ga pri klicu na toString () samo določite: // // s = baos.toString ("Cp1251");
Za več informacij o pogostih napakah glejte poglavje.

8-bitno kodiranje ruskih črk

Tu so glavna 8-bitna kodiranja ruskih črk, ki so postala zelo razširjena:

Poleg glavnega imena se lahko uporabljajo tudi sopomenke. Njihov nabor se lahko razlikuje v različnih različicah JDK. Tu je seznam iz 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
    • Cirilica
    • CSISOLatinCirilica
    • IBM915
    • IBM-915
    • Cp915

Poleg tega sopomenke, za razliko od glavnega imena, ne razlikujejo med velikimi in malimi črkami - to je značilnost izvedbe.

Omeniti velja, da ta kodiranja morda niso na voljo na nekaterih JVM -jih. Na primer, s spletnega mesta Sun lahko prenesete dve različici JRE - ameriško in mednarodno. V ameriški različici obstaja le minimum-ISO-8859-1, ASCII, Cp1252, UTF8, UTF16 in več različic dvobajtne Unicode. Vse ostalo je na voljo samo v mednarodni različici. Včasih lahko zaradi tega z zagonom programa naletite na grablje, tudi če ne potrebuje ruskih črk. Tipična napaka, ki se pojavi pri tem:

Med inicializacijo VM java / lang / ClassNotFoundException je prišlo do napake: sun / io / ByteToCharCp1251

Nastane, kot ni težko uganiti, zaradi dejstva, da JVM na podlagi ruskih regionalnih nastavitev poskuša nastaviti privzeto kodiranje v Cp1251, a ker razred takšne podpore v ameriški različici ni, se seveda prekine.

Datoteke in podatkovni tokovi

Tako kot so bajti konceptualno ločeni od znakov, Java razlikuje med bajtnimi tokovi in ​​tokovi znakov. Delo z bajti je predstavljeno z razredi, ki neposredno ali posredno podedujejo razrede InputStream ali OutputStream (plus edinstven razred RandomAccessFile). Delo s simboli predstavlja sladek par razredov Bralci / Pisatelji (in njihovi potomci, seveda).

Niz bajtov se uporablja za branje / pisanje nepreoblikovanih bajtov. Če veste, da bajti predstavljajo samo znake v določenem kodiranju, lahko uporabite posebne razrede pretvornikov InputStreamReader in OutputStreamWriter, da dobite tok znakov in neposredno delate z njimi. To je običajno uporabno za datoteke z navadnim besedilom ali pri delu z mnogimi internetnimi omrežnimi protokoli. V tem primeru je kodiranje znakov podano v konstruktorju razreda pretvornika. Primer:

// niz Unicode String string = "..."; // Zapišite niz v besedilno datoteko v kodiranju Cp866 PrintWriter pw = nov PrintWriter // razred z metodami za pisanje nizov(nov OutputStreamWriter // razred-pretvornik(nov FileOutputStream ("file.txt"), "Cp866"); pw.println (niz); // zapišemo vrstico v datoteko pw.close ();

Če lahko tok vsebuje podatke v različnih kodiranjih ali pa so znaki pomešani z drugimi binarnimi podatki, je bolje prebrati in zapisati bajtne matrike (bajte) in za pretvorbo uporabiti že omenjene metode razreda String. Primer:

// niz Unicode String string = "..."; // Zapišite niz v besedilno datoteko v dveh kodiranjih (Cp866 in Cp1251) OutputStream os = nov FileOutputStream ("file.txt"); // razred za zapisovanje bajtov v datoteko // Zapišite niz v kodiranje Cp866 os.write (string.getBytes ("Cp866")); // Zapišite niz v kodiranju Cp1251 os.write (string.getBytes ("Cp1251")); os.close ();

Konzola v Javi je tradicionalno predstavljena s tokovi, žal pa ne znaki, ampak bajti. Dejstvo je, da so se tokovi znakov pojavili le v JDK 1.1 (skupaj s celotnim mehanizmom kodiranja), dostop do konzolnih V / I pa je bil zasnovan v JDK 1.0, kar je privedlo do pojava čudaka v obliki razreda PrintStream. Ta razred se uporablja v spremenljivkah System.out in System.err, ki dejansko omogočata dostop do izhoda v konzolo. Vsekakor je to tok bajtov, vendar s kopico metod za pisanje nizov. Ko vanj vnesete niz, se s privzetim kodiranjem pretvori v bajte, kar je v primeru operacijskega sistema Windows običajno nesprejemljivo - privzeto kodiranje bo Cp1251 (Ansi), za okno konzole pa morate običajno uporabiti Cp866 ( OEM). Ta napaka je bila registrirana že v 97. letu (), a zdi se, da se Sun-ovac ne mudi popraviti. Ker v PrintStreamu ni načina za nastavitev kodiranja, lahko za rešitev te težave standardni razred zamenjate z lastnim z uporabo metod System.setOut () in System.setErr (). Tu je na primer običajen začetek mojih programov:

... javna statična void main (String args) ( // Nastavite izhod konzolnih sporočil v želeno kodiranje poskusite (String consoleEnc = System.getProperty ("console.encoding", "Cp866"); System.setOut (nov CodepagePrintStream (System.out, consoleEnc)); System.setErr (nov CodepagePrintStream (System.err, consoleEnc)); ) catch (UnsupportedEncodingException e) (System.out.println ("Ni mogoče nastaviti kodne strani konzole:" + e);) ...

Vire razreda CodepagePrintStream najdete na tem mestu: CodepagePrintStream.java.

Če sami oblikujete podatkovni format, vam priporočam, da uporabite eno od večbajtnih kodir. Najprimernejši format je običajno UTF8 - prvih 128 vrednosti (ASCII) v njem je kodiranih v enem bajtu, kar lahko pogosto znatno zmanjša skupno količino podatkov (ni zaman, da je to kodiranje osnova za svetu XML). Toda UTF8 ima eno pomanjkljivost - število potrebnih bajtov je odvisno od kode znakov. Kjer je to kritično, lahko uporabite enega od dvobajtnih formatov Unicode (UnicodeBig ali UnicodeLittle).

Baza podatkov

Za pravilno branje znakov iz baze podatkov je običajno dovolj, da gonilniku JDBC sporočite zahtevano kodiranje znakov v bazi podatkov. Kako natančno je odvisno od posameznega gonilnika. Dandanes to nastavitev podpira veliko voznikov, za razliko od nedavne preteklosti. Tukaj je nekaj primerov, ki jih poznam.

Most JDBC-ODBC

To je eden najpogosteje uporabljenih gonilnikov. Most iz JDK 1.2 in starejše je mogoče enostavno konfigurirati na želeno kodiranje. To naredimo tako, da v niz parametrov, ki so bili poslani za odpiranje povezave z bazo, dodamo dodatno lastnost charSet. Privzeto je file.encoding. To se naredi nekako takole:

// Vzpostavite povezavo

Oracle 8.0.5 JDBC-OCI gonilnik za Linux

Ko prejema podatke iz zbirke podatkov, ta gonilnik določi "njegovo" kodiranje s spremenljivko okolja NLS_LANG. Če te spremenljivke ni mogoče najti, predpostavlja, da je kodiranje ISO-8859-1. Trik je v tem, da mora biti NLS_LANG okoljska spremenljivka (nastavljena z ukazom set), ne pa sistemska lastnost Java (kot je file.encoding). Če se gonilnik uporablja znotraj motorja strežniških programčkov Apache + Jserv, lahko spremenljivko okolja nastavite v datoteki jserv.properties:

wrapper.env = NLS_LANG = American_America.CL8KOI8R
Podatke o tem je poslal Sergej Bezrukov, za kar se mu še posebej zahvaljuje.

Gonilnik JDBC za delo z DBF (zyh.sql.dbf.DBFDriver)

Ta voznik se je šele pred kratkim naučil delati z ruskimi črkami. Čeprav s strani getPropertyInfo () poroča, da razume lastnost charSet, je to le fikcija (vsaj v različici od 30. 7. 2001). V resnici lahko kodiranje prilagodite tako, da nastavite lastnost CODEPAGEID. Za ruske znake sta na voljo dve vrednosti - "66" za Cp866 in "C9" za Cp1251. Primer:

// Osnovni parametri povezave Lastnosti connInfo = nove lastnosti (); connInfo.put ("CODEPAGEID", "66"); // kodiranje Cp866 // Vzpostavite povezavo Povezava db = DriverManager.getConnection ("jdbc: DBF: / C: / MyDBFFiles", connInfo);
Če imate datoteke DBF v formatu FoxPro, potem imajo svoje posebnosti. Dejstvo je, da FoxPro v glavo datoteke shrani ID kodne strani (bajt z odmikom 0x1D), ki je bil uporabljen za ustvarjanje DBF. Pri odpiranju tabele gonilnik uporabi vrednost iz glave in ne parametra "CODEPAGEID" (parameter se v tem primeru uporablja le pri ustvarjanju novih tabel). V skladu s tem je za pravilno delovanje potrebno datoteko DBF ustvariti s pravilnim kodiranjem - sicer bodo težave.

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

S tem gonilnikom je vse tudi precej preprosto:

// Osnovni parametri povezave Lastnosti connInfo = nove lastnosti (); connInfo.put ("uporabnik", uporabnik); connInfo.put ("geslo", geslo); connInfo.put ("useUnicode", "true"); connInfo.put ("characterEncoding", "KOI8_R"); Povezava conn = DriverManager.getConnection (dbURL, rekviziti);

InterBase (interbase.interclient.Driver)

Za ta gonilnik deluje parameter "charSet":
// Osnovni parametri povezave Lastnosti connInfo = nove lastnosti (); connInfo.put ("uporabnik", uporabniško ime); connInfo.put ("geslo", geslo); connInfo.put ("charSet", "Cp1251"); // Vzpostavite povezavo Povezava db = DriverManager.getConnection (dataurl, connInfo);

Pri ustvarjanju baze podatkov in tabel pa ne pozabite navesti kodiranja znakov. Za ruski jezik lahko uporabite vrednosti "UNICODE_FSS" ali "WIN1251". Primer:

USTVARI PODATKOVNO BAZO ′ E: ProjectHoldingDataBaseHOLDING.GDB ′ PAGE_SIZE 4096 NASTAVITEV NASTAVLJENIH ZNAKOV UNICODE_FSS; USTVARI TABELO RUSSIAN_WORD ("NAME1" VARCHAR (40) CHARACTER SET UNICODE_FSS NOT NULL, "NAME2" VARCHAR (40) CHARACTER SET WIN1251 NOT NULL, PRIMARY KEY ("NAME1"));

V različici 2.01 InterClient je napaka - razredi virov s sporočili za ruski jezik tam niso pravilno sestavljeni. Najverjetneje so razvijalci pri sestavljanju preprosto pozabili navesti izvorno kodiranje. To napako lahko odpravite na dva načina:

  • Namesto interclient.jar uporabite interclient-core.jar. Hkrati ruskih virov preprosto ne bo, angleški pa bodo samodejno pobrani.
  • Znova prevedite datoteke v običajno Unicode. Razčlenjevanje datotek razreda je nehvaležna naloga, zato je bolje uporabiti JAD. Na žalost JAD, če naleti na znake iz nabora ISO-8859-1, jih prikaže v 8-mestnem kodiranju, zato ne boste mogli uporabljati standardnega kodirnika native2ascii-napisati morate svojega (program Decode). Če se ne želite ukvarjati s temi težavami, lahko vzamete že pripravljeno datoteko z viri (zakrpan kozarec z gonilnikom - interclient.jar, ločeni razredi virov - interclient -rus.jar).

Toda tudi če ste gonilnik JDBC nastavili na želeno kodiranje, lahko v nekaterih primerih naletite na težave. Ko na primer poskušate uporabiti čudovite nove drsne kazalce standarda JDBC 2 v mostu JDBC-ODBC iz JDK 1.3.x, hitro ugotovite, da ruske črke tam preprosto ne delujejo (metoda updateString ()).

S to napako je povezana majhna zgodba. Ko sem ga prvič odkril (pod JDK 1.3 rc2), sem ga registriral pri BugParade (). Ko je bila izdana prva beta različica JDK 1.3.1, je bila ta napaka označena kot odpravljena. Navdušen, prenesel sem to beta, opravil test - ne deluje. O tem sem pisal Sun -ovac - v odgovor so mi zapisali, da bo popravek vključen v prihodnje izdaje. V redu, sem si mislil, počakajmo. Čas je minil, izšla je izdaja 1.3.1 in nato beta 1.4. Končno sem si vzel čas za preverjanje - spet ne deluje. Mati, mati, mati ... - odmev je običajno odmeval. Po jeznem pismu Sun -u so uvedli novo napako (), ki so jo dali indijski veji, da jo raztrgajo. Indijanci so se poigravali s kodo in rekli, da je vse popravljeno v 1.4 beta3. Prenesel sem to različico, pod njo zagnal testni primer, tukaj je rezultat -. Izkazalo se je, da beta3, ki se distribuira na spletnem mestu (gradnja 84), ni beta3, kamor je bil vključen končni popravek (različica 87). Zdaj obljubljajo, da bo popravek vključen v 1.4 rc1 ... No, na splošno razumete :-)

Ruske črke v virih programov Java

Kot že omenjeno, program pri izvajanju uporablja Unicode. Izvorne datoteke so zapisane v običajnih urejevalnikih. Uporabljam Far, verjetno imate svojega najljubšega urejevalnika. Ti urejevalniki shranjujejo datoteke v 8-bitnem formatu, kar pomeni, da podobno sklepanje velja tudi za te datoteke. Različne različice prevajalnikov nekoliko drugače izvajajo pretvorbo znakov. Starejše različice JDK 1.1.x uporabljajo nastavitev file.encoding, ki jo je mogoče preglasiti z nestandardno možnostjo -J. V novejših (kot poroča Denis Kokarev - od 1.1.4) je bil uveden dodaten parameter kodiranja, s katerim lahko določite uporabljeno kodiranje. V prevedenih razredih so nizi predstavljeni v obliki Unicode (natančneje, v spremenjeni različici formata UTF8), zato se med kompilacijo zgodi najbolj zanimivo. Zato je najpomembnejše ugotoviti, v kakšnem kodiranju so vaše izvorne kode, in pri sestavljanju določite pravilno vrednost. Privzeto bo uporabljena ista razvpita koda file.encoding. Primer klicanja prevajalnika:

Poleg uporabe te nastavitve obstaja še ena metoda - določanje črk v formatu "uXXXX", kjer je označena koda znakov. Ta metoda deluje z vsemi različicami, za pridobitev teh kod pa lahko uporabite standardni pripomoček.

Če uporabljate kateri koli IDE, ima lahko svoje napake. Pogosto ti IDE uporabljajo privzeto kodiranje za branje / shranjevanje virov - zato bodite pozorni na regionalne nastavitve vašega OS. Poleg tega lahko pride do očitnih napak - na primer precej dober CodeGuide v merilu IDE ne prebavi dobro velike ruske črke "T". Vgrajeni analizator kode to črko jemlje kot dvojni narekovaj, kar vodi v dejstvo, da se pravilna koda dojema kot napačna. S tem se lahko borite (tako, da črko "T" zamenjate s kodo "u0422"), vendar neprijetno. Očitno se nekje znotraj razčlenjevalnika uporablja izrecna pretvorba znakov v bajte (na primer: bajt b = (bajt) c), zato je namesto kode 0x0422 (koda črke "T") koda 0x22 ( koda dvojnega narekovaja).

JBuilder ima še en problem, ki pa je bolj povezan z ergonomijo. Dejstvo je, da v JDK 1.3.0, pod katerim JBuilder privzeto deluje, obstaja napaka (), zaradi katere novo ustvarjena okna grafičnega vmesnika, ko so aktivirana, samodejno vključijo postavitev tipkovnice, odvisno od regionalnih nastavitev operacijskega sistema. Tisti. če imate ruske regionalne nastavitve, bo nenehno poskušal preiti na rusko postavitev, kar ovira pri pisanju programov. Spletno mesto JBuilder.ru ima nekaj popravkov, ki spremenijo trenutno področno nastavitev v JVM v Locale.US, vendar je najboljši način nadgradnja na JDK 1.3.1, ki je odpravil to napako.

Uporabniki novincev JBuilder se lahko srečajo tudi s takšno težavo - ruske črke se shranijo kot kode "uXXXX". Da bi se temu izognili, v pogovornem oknu Privzete lastnosti projekta, zavihek Splošno, v polju Kodiranje spremenite Privzeto v Cp1251.

Če za prevajanje uporabljate prevajalnik, ki ni standardni javac, bodite pozorni na to, kako izvaja pretvorbo znakov. Na primer, nekatere različice prevajalnika IBM jikes ne razumejo, da obstajajo kodiranja razen ISO-8859-1 :-). Za to so zakrpane različice, vendar je pogosto tudi tam šivano nekaj kodiranja - ni takšnega udobja kot v javac.

JavaDoc

Za ustvarjanje dokumentacije HTML za izvorno kodo se uporablja pripomoček javadoc, ki je vključen v standardno distribucijo JDK. Če želite določiti kodiranje, ima kar 3 parametre:

  • -kodiranje - ta nastavitev določa izvorno kodiranje. Privzeto je file.encoding.
  • -docencoding - ta nastavitev določa kodiranje ustvarjenih datotek HTML. Privzeto je file.encoding.
  • -charset - ta nastavitev določa kodiranje, ki bo zapisano v glave ustvarjenih datotek HTML ( ). Očitno bi moralo biti enako kot prejšnja nastavitev. Če je ta nastavitev izpuščena, metaoznaka ne bo dodana.

Ruske črke v datotekah lastnosti

Načini nalaganja virov se uporabljajo za branje datotek lastnosti, ki delujejo na poseben način. Pravzaprav se za branje uporablja metoda Properties.load, ki ne uporablja datoteke.encoding (kodiranje ISO-8859-1 je v virih trdo kodirano), zato je edini način za določitev ruskih črk uporaba oblike "uXXXX" in pripomoček.

Metoda Properties.save deluje drugače v JDK 1.1 in 1.2. V različici 1.1 je preprosto zavrgel visoki bajt, zato je pravilno deloval le z angleškimi črkami. 1.2 izvede obratno pretvorbo v "uXXXX", tako da deluje zrcalno na način nalaganja.

Če se datoteke z lastnostmi ne nalagajo kot viri, ampak kot navadne konfiguracijske datoteke in niste zadovoljni s tem vedenjem, obstaja le en izhod, napišite svoj nalagalnik.

Ruske črke v servletih.

No, čemu služijo ti isti servleti, mislim, da veste. Če ne, je najbolje, da najprej preberete dokumentacijo. Tu so opisane le posebnosti dela z ruskimi črkami.

Kakšne so torej lastnosti? Ko Servlet pošlje odgovor odjemalcu, obstajata dva načina za pošiljanje tega odgovora - prek OutputStream (metoda getOutputStream ()) ali prek PrintWriter (getWriter () metoda). V prvem primeru pišete matrike bajtov, zato veljajo zgornje metode pisanja v tokove. V primeru PrintWriter uporablja nastavljeno kodiranje. V vsakem primeru morate pravilno določiti kodiranje, ki se uporablja pri klicanju metode setContentType (), če želite pravilno pretvorbo znakov na strani strežnika. To direktivo je treba narediti pred klicem getWriter () ali pred prvim zapisom v OutputStream. Primer:

// Nastavimo kodiranje odziva // Upoštevajte, da nekateri motorji ne dovoljujejo // presledek med ';' in 'charset' response.setContentType ("besedilo / html; charset = UTF-8"); PrintWriter out = response.getWriter (); // Odpravljanje napak imena kodiranja za preverjanje out.println ("Encoding:" + response.getCharacterEncoding ()); ... out.close (); )

Gre za podajanje odgovorov stranki. Žal z vhodnimi parametri ni tako enostavno. Vhodne parametre kodira bajt brskalnika v skladu z vrsto MIME "application / x-www-form-urlencoded". Kot je dejal Aleksej Mendelev, brskalniki kodirajo ruske črke s trenutno nastavljenim kodiranjem. In o tem seveda nič ne poročajo. V skladu s tem se na primer v različicah JSDK od 2.0 do 2.2 to nikakor ne preveri in kakšno kodiranje bo uporabljeno za pretvorbo, je odvisno od uporabljenega motorja. Od specifikacije 2.3 je bilo mogoče nastaviti kodiranje za javax.servlet.ServletRequest - metodo setCharacterEncoding (). Najnovejše različice Resin in Tomcat že podpirajo to specifikacijo.

Če imate srečo in imate strežnik s podporo Servlet 2.3, je vse precej preprosto:

public void doPost (zahteva HttpServletRequest, odgovor HttpServletResponse) vrže ServletException, IOException ( // Kodiranje sporočil request.setCharacterEncoding ("Cp1251"); Niz vrednost = request.getParameter ("vrednost"); ...

Obstaja ena pomembna subtilnost pri uporabi metode request.setCharacterEncoding () - uporabiti jo je treba prej prvi klic na zahtevo po podatkih (na primer request.getParameter ()). Če uporabljate filtre, ki obdelajo zahtevo, preden prispe v servlet, obstaja možnost, da ni nič, da se v enem od filtrov iz zahteve odčita kakšen parameter (na primer za avtorizacijo) in request.setCharacterEncoding () v servlet ne bo deloval ...

Zato je ideološko pravilneje napisati filter, ki nastavi kodiranje zahteve. Poleg tega mora biti prvi v verigi filtrov v web.xml.

Primer takega filtra:

uvoz java.io. *; uvoz java.util. *; uvoz javax.servlet. *; uvoz javax.servlet.http. *; javni razred CharsetFilter izvaja Filter (// kodiranje zasebnega kodiranja niza; javna void init (konfiguracija FilterConfig) vrže ServletException ( // branje iz konfiguracije encoding = config.getInitParameter ("requestEncoding"); // če ni nameščen, namestite Cp1251 if (encoding == null) encoding = "Cp1251"; ) public void doFilter (zahteva ServletRequest, odgovor ServletResponse, naslednji FilterChain) vrne IOException, ServletException (request.setCharacterEncoding (encoding); next.doFilter (request, response);) public void kill () ())

In njegova konfiguracija v web.xml:

Filter nabojev CharsetFilter Filter nabojev /*

Če nimate sreče in imate starejšo različico, se boste morali za dosego rezultata spreobrniti:

    Izvirni način dela s kodiranjem ponuja ruski Apache - natančno je opisano, kako.

  • FOP

    Paket FOP je zasnovan za obdelavo dokumentov v skladu s standardom XSL FO (oblikovanje predmetov). Zlasti omogoča ustvarjanje dokumentov PDF na podlagi Dokumenti XML... Paket FOP privzeto uporablja procesor Xalan XSLT, povezan s Xercesom, za preoblikovanje iz izvornega XML v FO. Če želite ustvariti končno sliko v FOP -u, morate povezati pisave, ki podpirajo ruske črke. Za različico 0.20.1 lahko to storite tako:

    1. Kopirajte datoteke ttf iz sistemskega imenika Windows v podimenik conffonts (na primer v c: fop-0.20.1conffonts). Arial normal / normal, normal / bold, italic / normal in italic / bold zahtevajo datoteke arial.ttf, arialbd.ttf, ariali.ttf in arialbi.ttf.
    2. Ustvarite datoteke z opisom pisave (na primer arial.xml). Če želite to narediti, morate za vsako pisavo zagnati ukaz (to je za Arial normalno / normalno, vse v eni vrstici):
      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. V FOP v conf / userconfig.xml dodajte opis pisave z ruskimi črkami, na primer:
      Arial normal / bold, italic / normal in italic / bold so dodani podobno.
    4. Ko kličete FOP od ukazna vrstica po org.apache.fop.apps.Fop piše -c c: fop -0.20.1confuserconfig.xml Če morate uporabljati FOP iz strežniškega programčka, morate v strežniškem programčku za vrstico
      Voznik voznik= nov gonilnik ();
      dodaj vrstice:
      // Imenik pisav (c: weblogicfonts) je bil ustvarjen samo za udobje. Niz userConfig = "pisave / userconfig.xml"; Datoteka userConfigFile = nova datoteka (userConfig); Možnosti možnosti = nove možnosti (userConfigFile);
      Nato lahko določite lokacijo datotek ttf v datoteki userconfig.xml glede na koren aplikacijskega strežnika, ne da bi podali absolutno pot:
    5. V datoteko FO (ali XML in XSL) pred uporabo pisave napišite:
      font-family = "Arial" font-weight = "bold" (Če uporabljate Arial bold) font-style = "italic" (Če uporabljate Arial italic)

    Ta algoritem je poslal Aleksej Tyurin, za kar se mu posebno zahvaljuje.

    Če uporabljate pregledovalnik, vgrajen v FOP, morate upoštevati njegove posebnosti. Čeprav se domneva, da so napisi v njem rusificirani, je bilo to storjeno z napako (v različici 0.19.0). Za nalaganje oznak iz datotek virov paket org.apache.fop.viewer.resources uporablja svoj nalagalnik (razred org.apache.fop.viewer.LoadableProperties). Branje kodiranja je tam trdo kodirano (8859_1, kot v primeru Properties.load ()), vendar podpora za tip "uXXXX" ni izvedena. To napako sem prijavil razvijalcem, v načrte so vključili popravek.

    Med drugim obstaja spletno mesto, namenjeno rusifikaciji FOP (http://www.openmechanics.org/rusfop/), kjer najdete distribucijski komplet FOP z že popravljenimi napakami in povezanimi ruskimi pisavami.

    CORBA

    Standard CORBA določa tip, ki ustreza vrsti nizov Java. To je vrsta wstringa. Vse je v redu, vendar nekateri strežniki CORBA ne podpirajo