Programmering

Java Tip 112: Forbedre tokenisering av informasjonsrike strenger

De fleste Java-programmerere har brukt java.util.StringTokenizer klasse på et eller annet tidspunkt. Det er en praktisk klasse som i utgangspunktet tokeniserer (bryter) inngangsstrengen basert på en separator, og leverer tokens på forespørsel. (Tokenization er å gjøre sekvenser av tegn til tokens som er forstått av programmet ditt.)

Selv om det er praktisk, StringTokenizerfunksjonalitet er begrenset. Klassen leter bare etter avgrenseren i inngangsstrengen og bryter strengen når avgrenseren er funnet. Den sjekker ikke for forhold som om avgrenseren er innenfor en understreng, og returnerer heller ikke tokenet som "" (strenglengde 0) når to påfølgende avgrensere er funnet i inngangen. For å oppfylle disse begrensningene følger Java 2-plattformen (JDK 1.2 og fremover) med BreakIterator klasse, som er en forbedret tokenizer over StringTokenizer. Siden en slik klasse ikke er til stede i JDK 1.1.x, bruker utviklere ofte mye tid på å skrive en original tokenizer som oppfyller deres krav. I et stort prosjekt som involverer håndtering av dataformat, er det ikke uvanlig å finne mange slike tilpassede klasser som flyter rundt.

Dette tipset tar sikte på å veilede deg gjennom å skrive en sofistikert tokenizer ved å bruke den eksisterende StringTokenizer.

StringTokenizer begrensninger

Du kan opprette en StringTokenizer ved å bruke en av de følgende tre konstruktørene:

  1. StringTokenizer (String sInput): Bryter på hvite mellomrom ("", "\ t", "\ n").
  2. StringTokenizer (String sInput, String sDelimiter): Bryter videre avgrenser.
  3. StringTokenizer (String sInput, String sDelimiter, boolean bReturnTokens): Bryter videre avgrenser, men hvis bReturnTokens er satt til sant, så returneres også skillet som et token.

Den første konstruktøren sjekker ikke om inngangsstrengen inneholder understrenger. Når strengen "hallo. I dag \" skal jeg \ "til hjembyen min" er tokenisert på hvit plass, er resultatet i tokens Hallo., I dag, "JEG, er, ", går, i stedet for Hallo., I dag, "Jeg er ", går.

Den andre konstruktøren sjekker ikke avgrensernes fortløpende utseende. Når strengen "bok, forfatter, utgivelse ,,, utgivelsesdato" er tokenisert på ",", den StringTokenizer returnerer fire tokens med verdier bok, forfatter, utgivelse, og dato publisert i stedet for de seks verdiene bok, forfatter, utgivelse, "", "", og dato publisert, hvor "" betyr streng med lengde 0. For å få seks må du stille inn StringTokenizers bReturnTokens parameter til sann.

Funksjonen ved å sette parameteren til sant er viktig, da den gir en ide om tilstedeværelsen av påfølgende avgrensere. For eksempel, hvis dataene oppnås dynamisk og brukes til å oppdatere en tabell i en database, der inngangstokenene tilordnes til kolonneverdiene, kan vi ikke tilordne tokens med databasekolonner, da vi ikke er sikre på hvilke kolonner som skal settes til "". For eksempel vil vi legge til poster i en tabell med seks kolonner, og inndataene inneholder to påfølgende avgrensere. Resultatet fra StringTokenizer i dette tilfellet er fem tokens (ettersom to påfølgende avgrensninger representerer token "", hvilken StringTokenizer forsømmelser), og vi må sette seks felt. Vi vet heller ikke hvor den påfølgende avgrenseren vises, og dermed hvilken kolonne som skal settes til "".

Den tredje konstruktøren vil ikke fungere hvis et token i seg selv er lik (i lengde og verdi) til avgrenseren og er i en understreng. Når strengen "bok, forfatter, publikasjon, \", \ ", publiseringsdato" er tokenisert (denne strengen inneholder , som et token, som er det samme som avgrenseren) på streng ,, resultatet er bok, forfatter, utgivelse, ", ", dato publisert (med seks tokens) i stedet for bok, forfatter, utgivelse, , (kommategnet), dato publisert (med fem poletter). Husk deg, til og med å sette inn bReturnTokens (tredje parameter til StringTokenizer) til sant vil ikke hjelpe deg i dette tilfellet.

Grunnleggende behov for en tokenizer

Før du håndterer koden, må du vite de grunnleggende behovene til en god tokenizer. Siden Java-utviklere er vant til StringTokenizer klasse, bør en god tokenizer ha alle de nyttige metodene som klassen gir, for eksempel hasMoreTokens (), nextToken (), countTokens ().

Koden for dette tipset er enkel og for det meste selvforklarende. I utgangspunktet har jeg brukt StringTokenizer klasse (opprettet med bReturnTokens satt til sant) internt og ga metoder nevnt som ovenfor. Siden i noen tilfeller skilletegn kreves som tokens (svært sjeldne tilfeller) mens det i noen ikke er det, må tokenizer levere skilletegn som et token på forespørsel. Når du oppretter en PowerfulTokenizer objektet, som bare overfører inngangsstrengen og avgrenseren, bruker den internt en StringTokenizer med bReturnTokens satt til sant. (Årsaken til dette er hvis en StringTokenizer er skapt uten bReturnTokens satt til sant, så er det begrenset i å overvinne problemene som er nevnt tidligere). For å håndtere tokenizer riktig, sjekker koden om bReturnTokens er satt til sant noen få steder (beregner totalt antall tokens og nextToken ()).

Som du kanskje har observert, PowerfulTokenizer implementerer Oppregning grensesnitt, og dermed implementere hasMoreElements () og nextElement () metoder som bare delegerer samtalen til hasMoreTokens () og nextToken (), henholdsvis. (Ved å implementere Oppregning grensesnitt, PowerfulTokenizer blir bakoverkompatibel med StringTokenizer.) La oss se på et eksempel. Si at inngangsstrengen er "hallo, i dag ,,, \" Jeg, er \ ", skal ,,, \" kjøpe, en, bok \ "" og avgrenseren er ,. Denne strengen når tokenisert returnerer verdier som vist i tabell 1:

Tabell 1: Verdier returnert av tokenisert streng
TypeAntall poletterTokens

StringTokenizer

(bReturnTokens = true)

19hallo:,: I dag:,:,:,: "Jeg:,: er":,: går til:,:,:,: "kjøp:,: a:,: bok" (her karakteren : skiller tokens)

PowerfulTokenizer

(bReturnTokens = true)

13hei:,: I dag:,: "": "": Jeg, er:,: skal til:,: "": "": kjøp en bok (hvor "" betyr lengde streng 0)

PowerfulTokenizer

(bReturnTokens = false)

9hallo: I dag: "": "": Jeg skal: "": "": kjøpe en bok

Inngangsstrengen inneholder 11 komma (,) tegn, hvorav tre er inne i understreng og fire vises fortløpende (som I dag,,, gjør to påfølgende kommaopptredener, det første kommaet er I dagskilletegn). Her er logikken i å beregne antall tokens i PowerfulTokenizer sak:

  1. I tilfelle av bReturnTokens = truemultipliser antall avgrensere inne i understrengene med 2 og trekk det beløpet fra den faktiske summen for å få token. Årsaken er, for substring "kjøp, en, bok", StringTokenizer vil returnere fem tokens (dvs. kjøp:,: a:,: bok), samtidig som PowerfulTokenizer vil returnere ett token (dvs. kjøp, en, bok). Forskjellen er fire (dvs. 2 * antall avgrensere inne i underlaget). Denne formelen holder godt for alle underlag som inneholder avgrensere. Vær oppmerksom på det spesielle tilfellet der selve symbolet tilsvarer avgrenseren; dette skal ikke redusere telleverdien.
  2. Tilsvarende for saken om bReturnTokens = falske, trekk verdien av uttrykket [total avgrensere (11) - påfølgende avgrensere (4) + antall avgrensere inne i understrengene (3)] fra den faktiske summen (19) for å få token. Siden vi ikke returnerer avgrensningene i dette tilfellet, er de (uten å vises sammenhengende eller inne i understrengene) til ingen nytte for oss, og formelen ovenfor gir oss totalt antall tokens (9).

Husk disse to formlene, som er hjertet til PowerfulTokenizer. Disse formlene fungerer i nesten alle tilfeller. Men hvis du har mer komplekse krav som ikke passer for disse formlene, må du vurdere forskjellige eksempler for å utvikle din egen formel før du skynder deg å kode.

 // sjekk om avgrenseren er innenfor en understreng for (int i = 1; i

De nextToken () metoden får tokens ved hjelp av StringTokenizer.nextToken, og ser etter dobbel sitattegn i token. Hvis metoden finner disse tegnene, får den flere tokens til den ikke finner noen med et dobbelt sitat. Det lagrer også token i en variabel (sPrevToken; se kildekode) for å kontrollere påfølgende avgrensningsopptredener. Hvis nextToken () finner påfølgende tokens som er lik avgrenseren, så returnerer den "" (streng med lengde 0) som token.

Tilsvarende hasMoreTokens () metoden sjekker om antall poletter som allerede er forespurt er mindre enn totalt antall poletter.

Spar utviklingstid

Denne artikkelen har lært deg hvordan du enkelt kan skrive en kraftig tokenizer. Ved å bruke disse konseptene kan du skrive komplekse tokenisatorer raskt, og dermed spare deg for betydelig utviklingstid.

Bhabani Padhi er en Java-arkitekt og programmerer som for tiden jobber med utvikling av nett- og bedriftsapplikasjoner ved bruk av Java-teknologi i UniteSys, Australia. Tidligere jobbet han i Baltimore Technologies, Australia med produktutvikling for e-sikkerhet og i Fujitsu, Australia på et EJB-serverutviklingsprosjekt. Bhabanis interesser inkluderer distribuert databehandling, mobil og webapplikasjonsutvikling ved hjelp av Java-teknologi.

Lær mer om dette emnet

  • Få kildekoden for dette tipset

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

  • For mer informasjon om BreakIterator

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

  • Vis alle forrige Java-tips og send inn dine egne

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

  • For mer Introduksjonsnivå artikler, besøk JavaWorld 's Aktuell indeks

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

  • Lær Java fra grunnen av i JavaWorld 's Java 101 kolonne

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

  • Java-eksperter svarer på de tøffeste Java-spørsmålene dine i JavaWorld 's Java Q&A kolonne

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

  • Registrer deg for JavaWorld denne uken gratis ukentlig e-post nyhetsbrev for å finne ut hva som er nytt på JavaWorld

    //www.idg.net/jw-abonnement

Denne historien, "Java Tip 112: Improve tokenization of information-rich strings" ble opprinnelig utgitt av JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found