Ohjelmointi

Tarkempi kuvaus Java-merkkityypistä

Java 1.1 -versio tuo käyttöön useita luokkia merkkien käsittelyyn. Nämä uudet luokat luovat abstraktin muunnettavaksi alustakohtaisesta käsitteestä merkkiarvot Unicode arvot. Tässä sarakkeessa tarkastellaan mitä on lisätty, ja motiiveja näiden merkkiluokkien lisäämiseen.

Tyyppi hiiltyä

Ehkä kaikkein väärin käytetty C-kielen perustyyppi on tyyppi hiiltyä. hiiltyä tyyppiä käytetään väärin osittain, koska sen määritetään olevan 8 bittiä, ja viimeisten 25 vuoden aikana 8 bittiä on määritellyt myös pienimmän jakamattoman osan tietokoneista. Kun yhdistät jälkimmäisen tosiasian siihen, että ASCII-merkistö määritettiin sopimaan 7 bittiin, hiiltyä tyyppi tekee erittäin kätevästä "universaalista" tyypistä. Lisäksi C: ssä osoitin tyypin muuttujalle hiiltyä tuli yleinen osoitintyyppi, koska kaikki, johon voidaan viitata a hiiltyä voidaan myös viitata mihin tahansa muuhun tyyppiin käyttämällä valua.

Käyttö ja väärinkäyttö hiiltyä tyyppi C-kielellä johti moniin yhteensopimattomuuksiin kääntäjän toteutusten välillä, joten C: n ANSI-standardissa tehtiin kaksi erityistä muutosta: Yleisosoitin määriteltiin uudelleen siten, että siinä oli tyhjiötyyppi, mikä vaati ohjelmoijan nimenomaista ilmoitusta; ja merkkien numeerisen arvon katsottiin allekirjoitetuksi, mikä määritteli, miten niitä kohdellaan, kun niitä käytetään numeerisissa laskelmissa. Sitten 1980-luvun puolivälissä insinöörit ja käyttäjät tajusivat, että 8 bittiä ei riittänyt edustamaan kaikkia merkkejä maailmassa. Valitettavasti siihen aikaan C oli niin vakiintunut, että ihmiset eivät halunneet, ehkä edes kykenemättömiä muuttamaan hiiltyä tyyppi. Vilkuta nyt eteenpäin 90-luvulle, Javan varhaisiin alkuihin. Yksi monista Java-kielen suunnittelussa asetetuista periaatteista oli, että merkit olisivat 16 bittiä. Tämä valinta tukee Unicode, tavanomainen tapa edustaa monia erilaisia ​​merkkejä monilla eri kielillä. Valitettavasti se loi myös vaiheen erilaisille ongelmille, joita korjataan vasta nyt.

Mikä hahmo on?

Tiesin olevani pulassa, kun huomasin kysymykseni: "Mitä sitten On merkki? "No, merkki on kirjain, eikö? Joukko kirjaimia muodostavat sanan, sanat muodostavat lauseita ja niin edelleen. Todellisuus on kuitenkin se, että hahmon esitys tietokoneen näytöllä , kutsui sitä glyph, lukuarvoon, joka määrittää kyseisen kuvion, jota kutsutaan a koodipiste, ei ole oikeastaan ​​suoraviivaista ollenkaan.

Pidän itseäni onnekkaana englannin äidinkielenä. Ensinnäkin, koska se oli huomattavan määrän niiden ihmisten yhteinen kieli, jotka osallistuivat nykyajan digitaalisen tietokoneen suunnitteluun ja kehittämiseen; toiseksi, koska siinä on suhteellisen pieni määrä kuvioita. ASCII-määritelmässä on 96 tulostettavaa merkkiä, joita voidaan käyttää englannin kirjoittamiseen. Vertaa tätä kiinaan, jossa on määritelty yli 20 000 glyfiä ja määritelmä on puutteellinen. Morse- ja Baudot-koodin alkuajoista lähtien englannin kielen yleinen yksinkertaisuus (muutama kuviokuva, ulkonäön tilastollinen esiintymistiheys) on tehnyt siitä digitaalisen aikakauden lingua-francan. Mutta kun digitaaliseen aikakauteen siirtyvien ihmisten määrä on kasvanut, myös muiden kuin englanninkielisten äidinkielenään puhuvien määrä on kasvanut. Lukujen kasvaessa yhä useammat ihmiset olivat haluttomia hyväksymään, että tietokoneet käyttävät ASCII-tekniikkaa ja puhuvat vain englantia. Tämä lisäsi huomattavasti ymmärrettävien "merkkien" tietokoneiden määrää. Tämän seurauksena tietokoneiden koodaamien kuvioiden määrä oli kaksinkertaistettava.

Käytettävissä olevien merkkien määrä kaksinkertaistui, kun kunnioitettava 7-bittinen ASCII-koodi sisällytettiin 8-bittiseen merkkikoodaukseen nimeltä ISO Latin-1 (tai ISO 8859_1, "ISO" on Kansainvälinen standardointijärjestö). Kuten olet ehkä kerännyt koodaavalla nimellä, tämä standardi mahdollisti monien Euroopan mantereella käytettyjen latinankielisten kielten edustamisen. Se, että standardi luotiin, ei kuitenkaan tarkoittanut, että se oli käyttökelpoinen. Tuolloin monet tietokoneet olivat jo alkaneet käyttää muita 128 "merkkiä", joita saattoi edustaa 8-bittinen merkki. Kaksi jäljellä olevaa esimerkkiä näiden ylimääräisten merkkien käytöstä ovat IBM Personal Computer (PC) ja kaikkien aikojen suosituin tietokonepääte, Digital Equipment Corporation VT-100. Jälkimmäinen elää edelleen pääteemulaattoriohjelmiston muodossa.

8-bittisen hahmon todellisesta kuolemanajasta keskustellaan epäilemättä vuosikymmenien ajan, mutta kiinnitin sen Macintosh-tietokoneen käyttöönottoon vuonna 1984. Macintosh toi valtavirtaan kaksi hyvin mullistavaa käsitettä: merkkifontit, jotka oli tallennettu RAM; ja WorldScript, joita voidaan käyttää merkkien esittämiseen millä tahansa kielellä. Tietysti tämä oli yksinkertaisesti kopio siitä, mitä Xerox oli toimittanut Dandelion-luokan koneillaan Star-tekstinkäsittelyjärjestelmän muodossa, mutta Macintosh toi nämä uudet merkistöjoukot ja kirjasimet yleisölle, joka käytti edelleen "mykkäjä" päätteitä . Aloitettuaan eri kirjasinten käyttöä ei voitu lopettaa - se oli aivan liian houkutteleva liian monille ihmisille. 80-luvun loppupuolella paine kaikkien näiden merkkien käytön yhtenäistämiseksi tuli päähän perustamalla Unicode-konsortio, joka julkaisi ensimmäisen eritelmänsä vuonna 1990. Valitettavasti 80-luvulla ja jopa 90-luvulla merkistöjen määrä kerrottuna. Hyvin harvat insinööreistä, jotka luovat tuolloin uusia merkkikoodeja, pitivät syntyvää Unicode-standardia elinkelpoisena, joten he loivat omat koodikartoituksensa kuviot. Joten vaikka Unicodea ei hyväksytty hyvin, käsitys siitä, että käytettävissä oli vain 128 tai enintään 256 merkkiä, oli ehdottomasti kadonnut. Macintoshin jälkeen eri kirjasinten tuesta tuli tekstinkäsittelyn välttämätön ominaisuus. Kahdeksan bittistä merkkiä oli haihtumassa sukupuuttoon.

Java ja Unicode

Tulin tarinaan vuonna 1992, kun liittyin Oak-ryhmään (Java-kieltä kutsuttiin tammeksi, kun se kehitettiin ensimmäisen kerran) Sunissa. Perustyyppi hiiltyä määritettiin olevan 16 allekirjoittamatonta bittiä, ainoa Java-allekirjoittamaton tyyppi. 16-bittisen hahmon perustelu oli, että se tukee kaikkia Unicode-merkkien esityksiä, jolloin Java sopii edustamaan merkkijonoja millä tahansa Unicoden tukemalla kielellä. Mutta merkkijonon edustaminen ja sen tulostaminen ovat aina olleet erillisiä ongelmia. Ottaen huomioon, että suurin osa Oak-ryhmän kokemuksista tuli Unix-järjestelmistä ja Unix-johdetuista järjestelmistä, mukavin merkistö oli jälleen ISO Latin-1. Ryhmän Unix-perinnön myötä Java I / O -järjestelmä mallinnettiin suurelta osin Unix-virran abstraktiosta, jolloin jokainen I / O-laite voidaan edustaa 8-bittisen tavun virralla. Tämä yhdistelmä jätti jonkin verran kielivirheitä 8-bittisen syöttölaitteen ja Java-16-bittisten merkkien välillä. Siten missä tahansa Java-merkkijonot jouduttiin lukemaan tai kirjoittamaan 8-bittisestä virrasta, siellä oli pieni koodi, hakkerointi, jotta 8-bittiset merkit voidaan maagisesti yhdistää 16-bittisiin unicodeihin.

Java-kehityspaketin (JDK) 1.0-versioissa syötehakkerointi oli DataInputStream luokassa, ja lähtöhakkerointi oli koko PrintStream luokassa. (Oikeastaan ​​oli nimetty syöttöluokka TextInputStream Java alfa 2 -julkaisussa, mutta DataInputStream hakata todellisessa julkaisussa.) Tämä aiheuttaa edelleen ongelmia aloitteleville Java-ohjelmoijille, koska he etsivät epätoivoisesti C-funktion Java-vastaavaa. getc (). Harkitse seuraavaa Java 1.0 -ohjelmaa:

tuo java.io. *; julkisen luokan väärennös {public static void main (String args []) {FileInputStream fis; DataInputStream dis; char c; kokeile {fis = new FileInputStream ("data.txt"); dis = uusi DataInputStream (fis); while (tosi) {c = dis.readChar (); System.out.print (c); System.out.flush (); jos (c == '\ n') rikkoa; } fis.close (); } catch (Poikkeus e) {} System.exit (0); }} 

Ensi silmäyksellä näyttää siltä, ​​että tämä ohjelma avaa tiedoston, lukee sen yhden merkin kerrallaan ja poistuu, kun ensimmäinen uusi rivi luetaan. Käytännössä saat kuitenkin roskapostia. Ja syy siihen, että saat roskaa, on se readChar lukee 16-bittisiä Unicode-merkkejä ja System.out.print tulostaa, mitä sen oletetaan olevan ISO Latin-1 8-bittisiä merkkejä. Jos kuitenkin vaihdat yllä olevan ohjelman käyttämään Lue rivi toiminto DataInputStream, se näyttää toimivan, koska koodi on Lue rivi lukee muodon, joka määritetään kulkevan nyökkäyksen avulla Unicode-määrittelylle "muokatuksi UTF-8: ksi". (UTF-8 on muoto, jonka Unicode määrittelee edustamaan Unicode-merkkejä 8-bittisessä syötevirrassa.) Java 1.0: n tilanteessa on siis, että Java-merkkijonot koostuvat 16-bittisistä Unicode-merkkeistä, mutta vain yksi kartoitus kartoittaa ISO Latin-1 -merkit Unicode-muotoon. Onneksi Unicode määrittelee koodisivun "0" - eli 256 merkkiä, joiden ylemmät 8 bittiä ovat kaikki nollia - vastaamaan täsmälleen ISO Latin-1 -sarjaa. Kartoitus on siis melko triviaalia, ja niin kauan kuin käytät vain ISO Latin-1 -merkkitiedostoja, sinulla ei ole ongelmia, kun tiedot poistuvat tiedostosta, Java-luokka manipuloi niitä ja kirjoittaa sitten tiedostoon uudelleen. .

Syötteen muuntokoodin haudattamisessa näihin luokkiin oli kaksi ongelmaa: Kaikki alustat eivät tallentaneet monikielisiä tiedostojaan muokatussa UTF-8-muodossa; ja varmasti näiden alustojen sovellukset eivät välttämättä odottaneet ei-latinalaisia ​​merkkejä tässä muodossa. Siksi toteutustuki oli epätäydellinen, eikä tarvittavaa tukea ollut helppo lisätä myöhempään julkaisuun.

Java 1.1 ja Unicode

Java 1.1 -julkaisu esitteli kokonaan uuden käyttöliittymäsarjan merkkien käsittelyyn, nimeltään Lukijat ja Kirjailijat. Muutin nimettyä luokkaa väärä ylhäältä nimettyyn luokkaan viileä. viileä luokka käyttää InputStreamReader luokka käsittelemään tiedostoa eikä DataInputStream luokassa. Ota huomioon, että InputStreamReader on uuden alaluokka Lukija luokka ja System.out on nyt a PrintWriter objekti, joka on Kirjailija luokassa. Tämän esimerkin koodi näkyy alla:

tuo java.io. *; public class cool {public static void main (String args []) {FileInputStream fis; InputStreamReader irs; char c; kokeile {fis = new FileInputStream ("data.txt"); irs = uusi InputStreamReader (fis); System.out.println ("Koodauksen käyttö:" + irs.getEncoding ()); kun taas (tosi) {c = (char) irs.read (); System.out.print (c); System.out.flush (); jos (c == '\ n') rikkoa; } fis.close (); } catch (Poikkeus e) {} System.exit (0); }} 

Ensisijainen ero tämän esimerkin ja edellisen koodiluettelon välillä on koodin käyttö InputStreamReader luokan sijaan DataInputStream luokassa. Toinen tapa, jolla tämä esimerkki eroaa edellisestä, on se, että on olemassa ylimääräinen rivi, joka tulostaa koodauksen, jota InputStreamReader luokassa.

Tärkeä seikka on, että nykyinen koodi, kun se on dokumentoimaton (ja näennäisesti tuntematon) ja upotettu getChar menetelmä DataInputStream luokka, on poistettu (itse asiassa sen käyttö on vanhentunut; se poistetaan tulevassa julkaisussa). Java-version 1.1 versiossa muunnoksen suorittava mekanismi on nyt koteloitu Lukija luokassa. Tämä kapselointi tarjoaa tavan Java-luokan kirjastoille tukea monenlaisia ​​ei-latinankielisten merkkien ulkoisia esityksiä samalla, kun käytät aina Unicodea sisäisesti.

Tietenkin, kuten alkuperäisessä I / O-alijärjestelmäsuunnittelussa, kirjoittamista suorittavissa lukuluokissa on symmetrisiä vastineita. Luokka OutputStreamWriter voidaan kirjoittaa merkkijonoja lähtövirtaan, luokkaan Puskuroitu kirjoittaja lisää puskurointikerroksen ja niin edelleen.

Vaihdetaanko syylät vai todellista edistystä?

Suunnittelun hieman ylevä tavoite Lukija ja Kirjailijaluokkien oli kesytettävä nykyistä hodge-podge-edustustandardeja samoille tiedoille tarjoamalla vakiomuotoinen tapa muuntaa edestakaisin vanhojen esitysten välillä - olipa se sitten Macintosh Kreikan tai Windowsin kyrillinen - ja Unicode. Joten Java-luokan, joka käsittelee merkkijonoja, ei tarvitse muuttua, kun se siirtyy alustalta toiselle. Tämä voi olla tarinan loppu, paitsi että nyt, kun muuntokoodi on kapseloitu, herää kysymys siitä, mitä kyseinen koodi olettaa.

Tutkiessani tätä saraketta sain mieleeni kuuluisan Xeroxin johtajan (ennen kuin se oli Xerox, kun se oli Haloid Company) lainauksen siitä, että kopiokone on tarpeeton, koska sihteerillä oli melko helppo laittaa pala hiilipaperia kirjoituskoneella ja tehdä kopio asiakirjasta, kun hän oli luomassa alkuperäistä. Tietysti jälkikäteen on selvää, että valokopiokone hyödyttää asiakirjan vastaanottavaa henkilöä paljon enemmän kuin asiakirjaa tuottava henkilö. JavaSoft on osoittanut samanlaisen oivalluksen merkkien koodaus- ja dekoodausluokkien käytöstä suunnitellessaan tätä järjestelmän osaa.