Programavimas

Išsamus „Java“ simbolių tipo žvilgsnis

1.1 versijos „Java“ pateikia daugybę klasių, skirtų simboliams tvarkyti. Šios naujos klasės sukuria abstrakciją, skirtą konvertuoti iš konkrečios platformos simbolių reikšmių sąvokos į „Unicode“ vertybes. Šiame stulpelyje apžvelgiama, kas buvo pridėta, ir motyvai, kaip pridėti šias simbolių klases.

Tipas char

Bene labiausiai piktnaudžiaujama pagrindine C kalba tipu char. char tipas yra iš dalies piktnaudžiaujamas, nes jis apibrėžiamas kaip 8 bitai, o per pastaruosius 25 metus 8 bitai taip pat apibrėžė mažiausią nedalomą kompiuterio atminties dalį. Kai sujungsite pastarąjį faktą su tuo, kad ASCII simbolių rinkinys buvo apibrėžtas taip, kad tilptų į 7 bitus, char tipas daro labai patogų „universalų“ tipą. Be to, C, žymeklis į tipo kintamąjį char tapo universaliu žymeklio tipu, nes viskas, ką galima būtų vadinti a char taip pat gali būti nurodoma kaip bet kuri kita rūšis, naudojant liejimą.

Naudojimasis ir piktnaudžiavimu char tipas C kalba sukėlė daug nesuderinamumų tarp kompiliatorių diegimų, todėl ANSI C standarte buvo atlikti du konkretūs pakeitimai: universalus rodyklė buvo apibrėžta iš naujo, kad būtų tuštumos tipas, todėl reikalingas aiškus programuotojo pareiškimas; o skaitinė simbolių vertė buvo laikoma pasirašyta, taip apibrėžiant, kaip jie bus traktuojami, kai bus naudojami skaičiuojant. Tada aštuntojo dešimtmečio viduryje inžinieriai ir vartotojai suprato, kad 8 bitų nepakanka visiems pasaulio simboliams reprezentuoti. Deja, iki to laiko C buvo taip įsitvirtinęs, kad žmonės nenorėjo, o gal net ir negalėjo pakeisti char tipo. Dabar žvelk į 90-uosius, į ankstyvąjį „Java“ pradžią. Vienas iš daugelio principų, išdėstytų kuriant „Java“ kalbą, buvo tas, kad simboliai bus 16 bitų. Šis pasirinkimas palaiko „Unicode“, standartinis būdas atvaizduoti daugybę skirtingų simbolių įvairiomis kalbomis. Deja, tai taip pat nustatė įvairių problemų, kurios tik dabar yra šalinamos, etapą.

Kas vis dėlto yra personažas?

Žinojau, kad turiu bėdų, kai pajutau sau klausimą: „Na ir kas yra personažas? "Na, personažas yra raidė, tiesa? Rinkų krūva sudaro žodį, žodžiai sudaro sakinius ir pan. Tačiau tikrovė yra ta, kad santykis tarp simbolio atvaizdavimo kompiuterio ekrane , pavadino ją glifas, iki skaitinės vertės, nurodančios tą glifą, vadinamą a kodo taškas, iš tikrųjų nėra visiškai paprasta.

Manau, kad pasisekė, kad esu gimtoji anglų kalba. Pirma, todėl, kad tai buvo daugelio tų, kurie prisidėjo kuriant ir kuriant šiuolaikinį skaitmeninį kompiuterį, bendrinė kalba; antra, nes jame yra palyginti nedaug glifų. ASCII apibrėžime yra 96 ​​spausdintini simboliai, kuriuos galima naudoti rašant angliškai. Palyginkite tai su kinų kalba, kur apibrėžta daugiau kaip 20 000 glifų ir ši apibrėžtis nėra išsami. Nuo pat ankstyvųjų Morzės ir Baudoto kodų pradžios bendras anglų kalbos paprastumas (nedaug glifų, statistinis išvaizdos dažnis) pavertė jį skaitmeninio amžiaus lingua-franca. Didėjant į skaitmeninį amžių įžengiančių žmonių skaičiui, didėjo ir angliškai ne gimtąja kalba gyvenančių žmonių skaičius. Augant skaičiui, vis daugiau žmonių vis labiau nenorėjo sutikti, kad kompiuteriai naudoja ASCII ir kalba tik angliškai. Tai labai padidino „simbolių“ kompiuterių, reikalingų suprasti, skaičių. Todėl kompiuterių užkoduotų glifų skaičius turėjo padvigubėti.

Galimų simbolių skaičius padvigubėjo, kai gerbiamas 7 bitų ASCII kodas buvo įtrauktas į 8 bitų simbolių kodavimą, vadinamą ISO Latin-1 (arba ISO 8859_1, „ISO“ yra Tarptautinė standartų organizacija). Kaip jūs galbūt rinkote pagal kodavimo pavadinimą, šis standartas leido atstovauti daugeliui lotynų kalbos kilusių kalbų, vartojamų Europos žemyne. Vien todėl, kad standartas buvo sukurtas, dar nereiškė, kad jis buvo tinkamas naudoti. Tuo metu daugelis kompiuterių jau pradėjo naudoti kitus 128 „simbolius“, kuriuos tam tikru pranašumu gali reikšti 8 bitų simbolis. Du išlikę šių papildomų simbolių naudojimo pavyzdžiai yra „IBM Personal Computer“ (PC) ir visų laikų populiariausias kompiuterių terminalas „Digital Equipment Corporation VT-100“. Pastarasis gyvena terminalo emuliatoriaus programinės įrangos pavidalu.

Apie tikrąjį 8 bitų simbolio mirties laiką, be abejo, bus diskutuojama dešimtmečius, tačiau aš jį susiejau su „Macintosh“ kompiuterio įvedimu 1984 m. „Macintosh“ į pagrindinius kompiuterius įtraukė dvi labai revoliucingas sąvokas: simbolių šriftus, kurie buvo saugomi RAM; ir „WorldScript“, kurie galėtų būti naudojami simbolių atvaizdavimui bet kuria kalba. Žinoma, tai buvo tiesiog „Xerox“ savo „Dandelion“ klasės mašinų „Star“ teksto apdorojimo sistemos pavidalu kopija, tačiau „Macintosh“ atvedė šiuos naujus simbolių rinkinius ir šriftus auditorijai, kuri vis dar naudojo „nebylius“ terminalus. . Pradėjus naudoti skirtingus šriftus nebuvo galima nutraukti - tai tiesiog buvo per daug patrauklus daugeliui žmonių. 8-ojo dešimtmečio pabaigoje spaudimas standartizuoti visų šių simbolių naudojimą kilo, kai buvo įkurtas „Unicode“ konsorciumas, kuris pirmąją specifikaciją paskelbė 1990 m. Deja, 80-aisiais ir net 90-aisiais padaugintas simbolių rinkinių skaičius. Labai nedaug inžinierių, kurie tuo metu kūrė naujus simbolių kodus, laikė besikuriantį „Unicode“ standartą perspektyviu, todėl jie sukūrė savo kodų susiejimus su simboliais. Taigi, nors „Unicode“ nebuvo gerai priimtas, minties, kad yra tik 128 arba daugiausia 256 simboliai, tikrai nebeliko. Po „Macintosh“ įvairių šriftų palaikymas tapo privaloma teksto apdorojimo funkcija. Aštuonių bitų simboliai išnyko.

„Java“ ir „Unicode“

Į istoriją patekau 1992 m., Kai prisijungiau prie „Oak“ grupės („Java“ kalba buvo vadinama ąžuolu, kai ji buvo sukurta pirmą kartą) „Sun“. Pagrindo tipas char buvo apibrėžta kaip 16 nepasirašytų bitų, vienintelis „Java“ nepasirašytas tipas. 16 bitų simbolio pagrindas buvo tas, kad jis palaikys bet kokį „Unicode“ simbolių atvaizdavimą, todėl „Java“ bus tinkama eilutėms pateikti bet kuria „Unicode“ palaikoma kalba. Tačiau galimybė reprezentuoti eilutę ir galimybė ją atspausdinti visada buvo atskiros problemos. Atsižvelgiant į tai, kad daugiausia „Oak“ grupės patirties įgijo „Unix“ sistemos ir „Unix“ išvestos sistemos, patogiausias simbolių rinkinys vėlgi buvo ISO Latin-1. Be to, turint „Unix“ grupės paveldą, „Java“ įvesties / išvesties sistema buvo iš esmės modeliuota naudojant „Unix“ srauto abstrakciją, pagal kurią kiekvieną įvesties / išvesties įrenginį galima pavaizduoti 8 bitų baitų srautu. Šis derinys paliko klaidų tarp 8 bitų įvesties įrenginio ir 16 bitų „Java“ simbolių kalboje. Taigi visur, kur reikėjo skaityti „Java“ eilutes iš 8 bitų srauto ar jas įrašyti, ten buvo nedidelis kodo kiekis, nulaužimas, kad magiškai susieti 8 bitų simbolius į 16 bitų unikalųjį kodą.

1.0 versijos „Java Developer Kit“ (JDK) versijose įvesties nulaužimas buvo „DataInputStream“ klasės, o išėjimo nulaužimas buvo visas „PrintStream“ klasė. (Tiesą sakant, buvo įvesties klasė, pavadinta „TextInputStream“ alfa 2 išleidus Java, tačiau jis buvo išstumtas „DataInputStream“ nulaužti tikrąjį leidimą.) Tai ir toliau kelia problemų pradedantiems „Java“ programuotojams, nes jie desperatiškai ieško „C“ funkcijos „Java“ atitikmens getc (). Apsvarstykite šią „Java 1.0“ programą:

importuoti java.io. *; public class fogus {public static void main (String args []) {FileInputStream fis; DataInputStream dis; char c; pabandykite {fis = new FileInputStream ("data.txt"); dis = naujas „DataInputStream“ (fis); while (tiesa) {c = dis.readChar (); System.out.print (c); System.out.flush (); jei (c == '\ n') pertrauka; } fis.close (); } sugavimas (e išimtis) {} System.exit (0); }} 

Iš pirmo žvilgsnio atrodytų, kad ši programa atidaro failą, perskaito jį po vieną simbolį ir išeina, kai perskaitoma pirmoji nauja eilutė. Tačiau praktiškai tai, ką gaunate, yra šlamšto išvestis. Priežastis, dėl kurios jūs gaunate šiukšlių, yra ta readChar skaito 16 bitų „Unicode“ simbolius ir System.out.print išspausdina tai, kas, jos manymu, yra „ISO Latin-1“ 8 bitų simboliai. Tačiau jei pakeisite aukščiau nurodytą programą, kad galėtumėte naudoti readLine funkcija „DataInputStream“, jis atrodys veikiantis, nes kodas yra readLine skaito formatą, kuris yra apibrėžtas praeinančiu linktelėjimu „Unicode“ specifikacijai kaip „modifikuotas UTF-8“. („UTF-8“ yra formatas, kurį „Unicode“ nurodo atvaizduoti „Unicode“ simbolius 8 bitų įvesties sraute.) Taigi „Java 1.0“ situacija yra tokia, kad „Java“ eilutės yra sudarytos iš 16 bitų „Unicode“ simbolių, tačiau yra tik vienas susiejimas, kuris atvaizduoja ISO „Latin-1“ simboliai į „Unicode“. Laimei, „Unicode“ apibrėžia kodo puslapį „0“ - tai yra 256 simboliai, kurių viršutiniai 8 bitai yra visi lygūs nuliui - kad jie tiksliai atitiktų ISO Latin-1 rinkinį. Taigi susiejimas yra gana nereikšmingas ir tol, kol jūs naudojate tik ISO Latin-1 simbolių failus, jums nebus jokių problemų, kai duomenys palieka failą, jais manipuliuoja „Java“ klasė ir tada perrašomi į failą .

Laidojant įvesties konversijos kodą į šias klases kilo dvi problemos: ne visos platformos saugojo daugiakalbius failus modifikuotu UTF-8 formatu; ir tikrai, šios platformos programos nebūtinai tikėjosi, kad tokia forma nėra lotyniški simboliai. Todėl diegimo palaikymas buvo neišsamus ir nebuvo jokio paprasto būdo pridėti reikiamą palaikymą vėlesniame leidime.

„Java 1.1“ ir „Unicode“

„Java 1.1“ leidimas pristatė visiškai naują sąsajų rinkinį, skirtą simboliams tvarkyti, vadinamą Skaitytojai ir Rašytojai. Modifikavau pavadintą klasę fiktyvus iš viršaus į klasę, pavadintą Saunus. Saunus klasė naudoja „InputStreamReader“ klasės, kad apdorotų failą, o ne „DataInputStream“ klasė. Prisimink tai „InputStreamReader“ yra poklasis naujojo Skaitytojas klasė ir System.out dabar yra a „PrintWriter“ objektas, kuris yra Rašytojas klasė. Šio pavyzdžio kodas rodomas žemiau:

importuoti java.io. *; public class cool {public static void main (String args []) {FileInputStream fis; „InputStreamReader irs“; char c; pabandykite {fis = new FileInputStream ("data.txt"); irs = naujas „InputStreamReader“ (fis); System.out.println ("Kodavimo naudojimas:" + irs.getEncoding ()); o (tiesa) {c = (char) irs.read (); System.out.print (c); System.out.flush (); jei (c == '\ n') pertrauka; } fis.close (); } sugavimas (e išimtis) {} System.exit (0); }} 

Pagrindinis skirtumas tarp šio pavyzdžio ir ankstesnio kodų sąrašo yra „InputStreamReader“ klasė, o ne „DataInputStream“ klasė. Kitas būdas, kaip šis pavyzdys skiriasi nuo ankstesnio, yra tai, kad yra papildoma eilutė, kuri išspausdina kodą, kurį naudoja „InputStreamReader“ klasė.

Svarbus dalykas yra tai, kad esamas kodas, kai jis buvo be dokumentų (ir neva nežinomas) ir įtrauktas į „getChar“ metodas „DataInputStream“ klasė, buvo pašalinta (iš tikrųjų jo naudojimas nebenaudojamas; jis bus pašalintas būsimame leidime). 1.1 versijos „Java“ versijoje konversiją atliekantis mechanizmas dabar yra įtrauktas į Skaitytojas klasė. Šis įklijavimas suteikia galimybę „Java“ klasės bibliotekoms palaikyti daug skirtingų išorinių ne lotynų kalbos simbolių vaizdų, visada naudojant „Unicode“ viduje.

Žinoma, kaip ir originalus įvesties / išvesties posistemio dizainas, yra ir simetriškų skaitymo klasių atitikmenų, kurie atlieka rašymą. Klasė „OutputStreamWriter“ gali būti naudojamas rašant eilutes į išvesties srautą, klasę „BufferedWriter“ pridedamas buferio sluoksnis ir pan.

Prekyba karpomis ar reali pažanga?

Šiek tiek iškilus tikslas Skaitytojas ir Rašytojasklasės turėjo prisijaukinti tai, kas šiuo metu yra „hodge-podge“ tos pačios informacijos pateikimo standartai, pateikdami standartinį būdą, kaip konvertuoti pirmyn ir atgal tarp palikimo - ar tai būtų „Macintosh“ graikų, ar „Windows kirilica“ -, ir „Unicode“. Taigi, „Java“ klasė, tvarkanti eilutes, neturi keistis, kai ji pereina iš platformos į platformą. Tai gali būti istorijos pabaiga, išskyrus tai, kad dabar, kai konversijos kodas yra apgaubtas, kyla klausimas, ką tas kodas prisiima.

Tyrinėdamas šią skiltį, man įsiminė garsi „Xerox“ vadovo citata (anksčiau ji nebuvo „Xerox“, kai ji buvo „Haloid Company“), kad kopijavimo aparatas yra nereikalingas, nes sekretoriui buvo gana lengva įdėti anglies popieriaus lapą rašomąja mašinėle ir pasidarykite dokumento kopiją, kol ji kūrė originalą. Žinoma, akivaizdu, kad akivaizdu, jog fotokopijos aparatas naudingas dokumentą gaunančiam asmeniui daug daugiau nei tą, kuris sukuria dokumentą. „JavaSoft“ parodė panašų nepakankamą supratimą apie simbolių kodavimo ir dekodavimo klasių naudojimą kuriant šią sistemos dalį.