Ohjelmointi

Java-vinkki 112: Paranna tietorikkaiden merkkijonojen tokenointia

Useimmat Java-ohjelmoijat ovat käyttäneet java.util.StringTokenizer luokassa jossakin vaiheessa. Se on kätevä luokka, joka periaatteessa merkitsee (rikkoo) erotinpohjaisen syöttömerkkijonon ja toimittaa tunnukset pyynnöstä. (Tokenisaatio on merkkijonojen muuttaminen tunnuksiksi, jotka ohjelmasi ymmärtää.)

Vaikka kätevä, StringTokenizertoiminnallisuus on rajoitettu. Luokka yksinkertaisesti etsii erotinta syöttömerkkijonosta ja rikkoo merkkijonon, kun erotin on löydetty. Se ei tarkista ehtoja, kuten onko erotin alaosassa, eikä se palauta tunnusta nimellä "" (merkkijonon pituus 0), kun syötteestä löytyy kaksi peräkkäistä erotinta. Näiden rajoitusten täyttämiseksi Java 2 -alustan (JDK 1.2 alkaen) mukana tulee BreakIterator luokka, joka on parannettu tokenizer over StringTokenizer. Koska tällaista luokkaa ei ole JDK 1.1.x -ohjelmassa, kehittäjät käyttävät usein paljon aikaa kirjoittamalla alkuperäisen tokenizerin, joka täyttää heidän vaatimuksensa. Suuressa projektissa, johon liittyy datamuotojen käsittelyä, ei ole harvinaista löytää monia tällaisia ​​räätälöityjä luokkia kelluvia.

Tämän vihjeen tarkoituksena on opastaa sinua kirjoittamaan hienostunut tokenizer käyttämällä olemassa olevaa StringTokenizer.

StringTokenizer-rajoitukset

Voit luoda StringTokenizer käyttämällä jotakin seuraavista kolmesta konstruktorista:

  1. StringTokenizer (String sInput): Taukot tyhjään tilaan ("", "\ t", "\ n").
  2. StringTokenizer (String sInput, String sDelimiter): Katkeaa sDelimiter.
  3. StringTokenizer (String sInput, String sDelimiter, looginen bReturnTokens): Katkeaa sDelimiter, mutta jos bReturnTokens on asetettu tosi, niin erotin palautetaan myös tunnuksena.

Ensimmäinen konstruktori ei tarkista, sisältääkö syötemerkkijono alijonoja. Kun merkkijono "hei. Tänään \" menen \ "kotikaupunkiini" on merkitty tyhjälle tilalle, tulos on merkkeinä Hei., Tänään, "Minä, olen, ", menossa, eikä Hei., Tänään, "Olen ", menossa.

Toinen konstruktori ei tarkista rajaimien peräkkäistä ulkonäköä. Kun merkkijono "kirja, kirjailija, julkaisu ,,, julkaisupäivä" on tokenoitu ",", StringTokenizer palauttaa neljä arvoa sisältävää rahaketta kirja, kirjailija, julkaisuja julkaisupäivä kuuden arvon sijaan kirja, kirjailija, julkaisu, "", ""ja julkaisupäivä, missä "" tarkoittaa merkkijonoa 0. Saadaksesi kuusi, sinun on asetettava StringTokenizeron bReturnTokens parametri tosi.

Ominaisuus asettaa parametri tosi on tärkeä, koska se antaa käsityksen peräkkäisten erottimien olemassaolosta. Esimerkiksi, jos tiedot saadaan dynaamisesti ja niitä käytetään tietokannan taulukon päivittämiseen, jossa syöttötunnukset vastaavat sarakkeen arvoja, emme voi kartoittaa tunnuksia tietokantasarakkeilla, koska emme ole varmoja, mitkä sarakkeet tulisi asettaa että "". Haluamme esimerkiksi lisätä tietueita taulukkoon, jossa on kuusi saraketta, ja syötetiedot sisältävät kaksi peräkkäistä erotinta. Tulos StringTokenizer tässä tapauksessa on viisi tunnusta (koska kaksi peräkkäistä erotinta edustavat tunnusta "", joka StringTokenizer laiminlyönnit), ja meidän on asetettava kuusi kenttää. Emme myöskään tiedä, missä peräkkäinen erotin näkyy, minkä sarakkeen tulisi olla "".

Kolmas konstruktori ei toimi, jos tunnus itsessään on (pituudeltaan ja arvoltaan) sama kuin erotin ja on alimerkkijonossa. Kun merkkijono "kirja, kirjailija, julkaisu, \", \ ", julkaisupäivä" on tokenoitu (tämä merkkijono sisältää , merkkinä, joka on sama kuin sen erotin) merkkijonossa ,, tulos on kirja, kirjailija, julkaisu, ", ", julkaisupäivä (kuuden tunnuksen kanssa) kirja, kirjailija, julkaisu, , (pilkku) julkaisupäivä (viidellä tunnuksella). Huomaa, jopa asettamalla bReturnTokens (kolmas parametri StringTokenizer) true ei auta sinua tässä tapauksessa.

Tokenizerin perustarpeet

Ennen kuin käsittelet koodia, sinun on tiedettävä hyvän tokenizerin perustarpeet. Koska Java-kehittäjät ovat tottuneet StringTokenizer luokassa, hyvällä tokenizerilla tulisi olla kaikki luokan tarjoamat hyödylliset menetelmät, kuten hasMoreTokens (), seuraavaToken (), countTokens ().

Tämän vinkin koodi on yksinkertainen ja enimmäkseen itsestään selvä. Pohjimmiltaan olen käyttänyt StringTokenizer luokka (luotu bReturnTokens asetettu tosi) sisäisesti ja toimittanut edellä mainitut menetelmät. Koska joissakin tapauksissa erotin vaaditaan tunnuksina (hyvin harvoissa tapauksissa), kun taas joissakin se ei ole, tunnisteiden on toimitettava erotin tunnuksina pyynnöstä. Kun luot a Tehokas Tokenizer välittää vain syötemerkkijonon ja erottimen, se käyttää sisäisesti a StringTokenizer kanssa bReturnTokens asetettu tosi. (Syynä tähän on, jos a StringTokenizer on luotu ilman bReturnTokens tosi, niin se on rajallinen aiemmin ilmoitettujen ongelmien voittamisessa). Käsitelläksesi tokenizeria oikein, koodi tarkistaa, onko bReturnTokens on tosi muutamissa paikoissa (lasketaan merkkien ja seuraavaToken ()).

Kuten olet ehkä huomannut, Tehokas Tokenizer toteuttaa Luettelointi käyttöliittymä ja siten toteuttaa hasMoreElements () ja seuraavaElement () menetelmiä, jotka yksinkertaisesti delegoivat puhelun hasMoreTokens () ja seuraavaToken ()vastaavasti. (Toteuttamalla Luettelointi käyttöliittymä, Tehokas Tokenizer tulee taaksepäin yhteensopiva StringTokenizer.) Tarkastellaan esimerkkiä. Sano, että syötemerkkijono on "hei, tänään ,,, \" minä, olen ", menen ,,, \" osta, a, kirja \ "" ja erotin on ,. Kun merkkijono merkitään, se palauttaa arvot taulukon 1 mukaisesti:

Taulukko 1: Tokenisoidun merkkijonon palauttamat arvot
TyyppiTunnusten määräTunnukset

StringTokenizer

(bReturnTokens = tosi)

19hei:,: Tänään:,:,:,: "I:,: am":,: going to:,:,:,: "buy:,: a:,: book" (tässä merkki : erottaa rahakkeet)

Tehokas Tokenizer

(bReturnTokens = tosi)

13hei:,: Tänään:,:: "": "": Minä, olen:,: menee:,: "": "": osta kirja (missä "" tarkoittaa merkkijonoa, jonka pituus on 0)

Tehokas Tokenizer

(bReturnTokens = väärä)

9hei: Tänään: "": "": Minä aion: "": "": ostaa kirjan

Syöttömerkkijono sisältää 11 pilkua (,) merkkiä, joista kolme on alaosassa ja neljä esiintyy peräkkäin (kuten Tänään,,, tekee kaksi peräkkäistä pilkkuja, ensimmäinen pilkku on Tänäänerottelija). Tässä on logiikka laskettaessa tunnusten määrää Tehokas Tokenizer tapaus:

  1. Siinä tapauksessa että bReturnTokens = tosi, kerro alarivien sisällä olevien erottimien lukumäärä 2: lla ja vähennä kyseinen määrä todellisesta kokonaismäärästä, jotta saat tunnuksen määrän. Syynä on alaosassa "osta, kirjaa", StringTokenizer palauttaa viisi rahaketta (ts. osta:,: a:,: kirja), sillä aikaa Tehokas Tokenizer palauttaa yhden tunnuksen (ts. osta, kirja). Ero on neljä (ts. 2 * erottimien lukumäärä alarivin sisällä). Tämä kaava sopii hyvin kaikille alariville, jotka sisältävät erottimia. Ole tietoinen erityistapauksesta, jossa tunnus itse vastaa erotinta; tämän ei pitäisi vähentää laskenta-arvoa.
  2. Samoin bReturnTokens = väärä, vähennä lausekkeen arvo [erottimien kokonaismäärä (11) - peräkkäiset erottimet (4) + erottimien lukumäärä alarivien sisällä (3)] todellisesta kokonaismäärästä (19), jotta saat tunnuksen määrän. Koska emme palauta erottimia tässä tapauksessa, niistä (ilman että ne näkyvät peräkkäin tai alaotsojen sisällä) ei ole meille hyötyä, ja yllä oleva kaava antaa meille merkkien kokonaismäärän (9).

Muista nämä kaksi kaavaa, jotka ovat Tehokas Tokenizer. Nämä kaavat toimivat melkein kaikissa vastaavissa tapauksissa. Jos sinulla on kuitenkin monimutkaisempia vaatimuksia, jotka eivät sovellu näihin kaavoihin, sinun on harkittava useita esimerkkejä oman kaavan kehittämiseksi ennen kuin aloitat koodaamisen.

 // tarkista onko erotin (int i = 1; i

seuraavaToken () menetelmä saa rahakkeita käyttämällä StringTokenizer.nextTokenja tarkistaa kaksoislainausmerkin merkistä. Jos menetelmä löytää nämä merkit, se saa enemmän merkkejä, kunnes se ei löydä kaksoislainausta. Se tallentaa myös tunnuksen muuttujaan (sPrevToken; katso lähdekoodia) peräkkäisten erottimien esiintymien tarkistamiseksi. Jos seuraavaToken () etsii peräkkäisiä tunnuksia, jotka ovat yhtä suuria kuin erotin, sitten se palaa "" (merkkijono, jonka pituus on 0) tunnuksena.

Samoin hasMoreTokens () menetelmä tarkistaa, onko jo pyydettyjen tunnusten määrä pienempi kuin tunnusten kokonaismäärä.

Säästä kehitysaikaa

Tämä artikkeli on opettanut, kuinka voit kirjoittaa tehokkaan tokenizerin helposti. Näiden käsitteiden avulla voit kirjoittaa monimutkaisia ​​tunnisteita nopeasti, mikä säästää merkittävästi kehitysaikaa.

Bhabani Padhi on Java-arkkitehti ja ohjelmoija, joka työskentelee parhaillaan Web- ja yrityssovellusten kehittämisessä Java-tekniikkaa käyttäen UniteSysissä, Australiassa. Aikaisemmin hän työskenteli Baltimore Technologiesissa Australiassa sähköisen turvallisuuden tuotekehityksessä ja Fujitsussa Australiassa EJB-palvelinkehitysprojektissa. Bhabanin kiinnostuksen kohteisiin kuuluvat hajautettu tietojenkäsittely, mobiili ja verkkosovellusten kehittäminen Java-tekniikkaa käyttäen.

Lisätietoja tästä aiheesta

  • Hanki tämän vihjeen lähdekoodi

    //images.techhive.com/downloads/idge/imported/article/jvw/2001/06/powerfultokenizer.java

  • Lisätietoja BreakIteratorista

    //java.sun.com/products/jdk/1.2/docs/api/java/text/BreakIterator.html

  • Näytä kaikki edelliset Java-vinkkejä ja lähetä oma

    //www.javaworld.com/javatips/jw-javatips.index.html

  • Lisää Johdantotaso artikkeleita, käy JavaWorld 's Ajankohtainen hakemisto

    //www.javaworld.com/javaworld/topicalindex/jw-ti-introlevel.html

  • Opettele Java alusta asti JavaWorld 's Java 101 sarake

    //www.javaworld.com/javaworld/topicalindex/jw-ti-java101.html

  • Java-asiantuntijat vastaavat vaikeimpiin Java-kysymyksiinsi JavaWorld 's Java-kysymykset ja vastaukset sarake

    //www.javaworld.com/javaworld/javaqa/javaqa-index.html

  • Rekisteröidy JavaWorld tällä viikolla ilmainen viikoittainen sähköpostiuutiskirje saadaksesi selville, mitä uutta on JavaWorld

    //www.idg.net/jw-subscribe

Tämän tarinan "Java Tip 112: Improve tokenization of information-rich strings" julkaisi alun perin JavaWorld.