Väčšina programátorov v jazyku Java používa program java.util.StringTokenizer
triedy v nejakom čase alebo inom. Je to šikovná trieda, ktorá v podstate tokenizuje (zlomí) vstupný reťazec na základe oddeľovača a na požiadanie dodá tokeny. (Tokenizácia je akt premeny sekvencií znakov na tokeny, ktorým váš program rozumie.)
Aj keď je to praktické, StringTokenizer
funkčnosť je obmedzená. Trieda jednoducho vyhľadá vo vstupnom reťazci oddeľovač a po nájdení oddeľovača reťazec rozbije. Nekontroluje podmienky, či je oddeľovač v podreťazci, ani nevráti token ako ""
(dĺžka reťazca 0), akonáhle sa vo vstupe nájdu dva po sebe idúce oddeľovače. Na splnenie týchto obmedzení prichádza platforma Java 2 (JDK 1.2 a novšia) s BreakIterator
triedy, čo je vylepšený tokenizer StringTokenizer
. Pretože takáto trieda v JDK 1.1.x nie je, vývojári často trávia veľa času písaním originálneho tokenizátora, ktorý spĺňa ich požiadavky. Vo veľkom projekte zahŕňajúcom spracovanie dátových formátov nie je nezvyčajné nájsť veľa takýchto prispôsobených tried, ktoré plávajú okolo.
Tento tip si kladie za cieľ sprevádzať písaním sofistikovaného tokenizéra s využitím existujúceho StringTokenizer
.
Obmedzenia StringTokenizer
Môžete vytvoriť StringTokenizer
pomocou ktoréhokoľvek z nasledujúcich troch konštruktorov:
StringTokenizer (String sInput)
: Prestávky na biele miesto ("", "\ t", "\ n"
).StringTokenizer (String sInput, String sDelimiter)
: Prestávky zapnutésDelimiter
.StringTokenizer (String sInput, String sDelimiter, boolean bReturnTokens)
: Prestávky zapnutésDelimiter
, ale akbReturnTokens
je nastavená na hodnotu true, potom sa ako token vráti aj oddeľovač.
Prvý konštruktér nekontroluje, či vstupný reťazec obsahuje podreťazce. Keď šnúrka "ahoj. Dnes \" idem \ "do môjho domovského mesta"
je tokenizovaný na prázdnom mieste, výsledok je v tokenoch Ahoj.
, Dnes
, „Ja
, am
, "
, ísť
, namiesto Ahoj.
, Dnes
, "Som "
, ísť
.
Druhý konštruktér nekontroluje po sebe idúci vzhľad oddeľovačov. Keď reťazec „kniha, autor, publikácia ,,, dátum vydania“
je tokenizovaný dňa ","
, StringTokenizer
vráti štyri tokeny s hodnotami kniha
, autor
, publikácia
a dátum zverejnenia
namiesto šiestich hodnôt kniha
, autor
, publikácia
, ""
, ""
a dátum zverejnenia
, kde ""
znamená reťazec dĺžky 0. Ak chcete získať šesť, musíte nastaviť StringTokenizer
je bReturnTokens
parameter na true.
Funkcia nastavenia parametra na true je dôležitá, pretože poskytuje predstavu o prítomnosti po sebe nasledujúcich oddeľovačov. Napríklad, ak sa údaje získavajú dynamicky a používajú sa na aktualizáciu tabuľky v databáze, kde sa vstupné tokeny mapujú na hodnoty stĺpcov, nemôžeme tokeny mapovať pomocou stĺpcov databázy, pretože si nie sme istí, ktoré stĺpce by sa mali nastaviť. do ""
. Napríklad chceme pridať záznamy do tabuľky so šiestimi stĺpcami a vstupné údaje obsahujú dva po sebe nasledujúce oddeľovače. Výsledok z StringTokenizer
v tomto prípade je to päť tokenov (keďže dva po sebe nasledujúce oddeľovače predstavujú token ""
, ktoré StringTokenizer
zanedbáva) a musíme nastaviť šesť polí. Tiež nevieme, kde sa objavuje následný oddeľovač, na ktorý stĺpec by sa mal nastaviť ""
.
Tretí konštruktor nebude fungovať, ak sa samotný token bude rovnať (dĺžkou a hodnotou) oddeľovaču a bude v podreťazci. Keď šnúrka "kniha, autor, publikácia, \", \ "dátum zverejnenia"
je tokenizovaný (tento reťazec obsahuje ,
ako token, ktorý je rovnaký ako jeho oddeľovač) na reťazci ,
, výsledok je kniha
, autor
, uverejnenie
, "
, "
, dátum zverejnenia
(so šiestimi žetónmi) namiesto kniha
, autor
, publikácia
, ,
(znak čiarky), dátum zverejnenia
(s piatimi žetónmi). Nezabudnite, dokonca aj nastavenie bReturnTokens
(tretí parameter do StringTokenizer
) na true vám v tomto prípade nepomôže.
Základné potreby tokenizéra
Predtým, ako začnete pracovať s kódom, musíte poznať základné potreby dobrého tokenizéra. Keďže vývojári Java sú zvyknutí na StringTokenizer
triedy, dobrý tokenizer by mal mať všetky užitočné metódy, ktoré trieda poskytuje, ako napr hasMoreTokens ()
, nextToken ()
, countTokens ()
.
Kód tohto tipu je jednoduchý a väčšinou je vysvetľujúci. V zásade som použil StringTokenizer
trieda (vytvorené pomocou bReturnTokens
nastavená na hodnotu true) interne a poskytla metódy uvedené vyššie. Pretože v niektorých prípadoch je oddeľovač vyžadovaný ako tokeny (veľmi zriedkavé prípady), zatiaľ čo v iných nie, musí tokenizátor na požiadanie dodať oddeľovač ako token. Keď vytvoríte a PowerfulTokenizer
objekt, ktorý odovzdáva iba vstupný reťazec a oddeľovač, interne používa a StringTokenizer
s bReturnTokens
nastavený na pravdivý. (Dôvodom je, ak a StringTokenizer
je vytvorený bez bReturnTokens
nastavená na hodnotu true, potom je obmedzená pri prekonávaní vyššie uvedených problémov). Pre správnu manipuláciu s tokenizérom kód skontroluje, či bReturnTokens
je na niekoľkých miestach nastavený na hodnotu true (výpočet celkového počtu tokenov a nextToken ()
).
Ako ste si mohli všimnúť, PowerfulTokenizer
realizuje Vymenovanie
rozhranie, čím sa implementuje hasMoreElements ()
a nextElement ()
metódy, ktoré jednoducho delegujú hovor na hasMoreTokens ()
a nextToken ()
, resp. (Implementáciou Vymenovanie
rozhranie, PowerfulTokenizer
stane sa spätne kompatibilným s StringTokenizer
.) Zvážme príklad. Povedzme, že vstupný reťazec je „ahoj, dnes ,,, \" ja, idem ", idem ,,, \" kúpiť, a, kniha \ ""
a oddeľovač je ,
. Tento reťazec pri tokenizácii vracia hodnoty, ako je uvedené v tabuľke 1:
Typ | Počet tokenov | Žetóny |
---|---|---|
| 19 | ahoj:,: Today:,:,:,: "I:,: am":,: chystám sa:,:,:,: "kúpiť:,: a:,: kniha " (tu postava : oddeľuje žetóny) |
| 13 | ahoj:,: Today:,: "": "": I, am:,: chystám sa:,: "": "": kúpiť knihu (kde "" znamená reťazec dĺžky 0) |
| 9 | ahoj: dnes: "": "": chystám sa: "": "": kúpiť si knihu |
Vstupný reťazec obsahuje 11 čiarok (,
) znaky, z ktorých tri sú vnútri podreťazcov a štyri sa objavujú postupne (ako Dnes ,,,
robí dve po sebe nasledujúce čiarky, prvá je čiarka Dnes
oddeľovač). Tu je logika pri výpočte počtu tokenov v PowerfulTokenizer
prípad:
- V prípade
bReturnTokens = true
, vynásobte počet oddeľovačov vo vnútri podreťazcov 2 a odčítajte túto sumu od skutočného súčtu, aby ste získali počet tokenov. Dôvod je pre podreťazec„kúpiť, rezervovať“
,StringTokenizer
vráti päť žetónov (t.j.kúpiť:,: a:,: kniha
), zatiaľ čoPowerfulTokenizer
vráti jeden token (tj.kúpiť, a, rezervovať
). Rozdiel sú štyri (tj. 2 * počet oddeľovačov vo vnútri podreťazca). Tento vzorec platí pre akýkoľvek podreťazec obsahujúci oddeľovače. Majte na pamäti špeciálny prípad, keď sa samotný token rovná oddeľovaču; toto by nemalo znižovať hodnotu počtu. - Podobne pre prípad
bReturnTokens = false
, od skutočnej sumy (19) odčítajte hodnotu výrazu [celkové oddeľovače (11) - po sebe idúce oddeľovače (4) + počet oddeľovačov vo vnútri podreťazcov (3)], aby ste získali počet tokenov. Pretože v tomto prípade nevraciame oddeľovače, sú pre nás (bez toho, aby sa vyskytli postupne alebo vo vnútri podreťazcov) k ničomu a vyššie uvedený vzorec nám dáva celkový počet tokenov (9).
Pamätajte na tieto dva vzorce, ktoré sú srdcom PowerfulTokenizer
. Tieto vzorce fungujú takmer pre všetky príslušné prípady. Ak však máte zložitejšie požiadavky, ktoré nie sú vhodné pre tieto vzorce, musíte pred tým, ako sa pustíte do programovania, zvážiť rôzne príklady, aby ste si vytvorili svoj vlastný vzorec.
// skontrolovať, či je oddeľovač v podreťazci pre (int i = 1; iThe
countTokens()
method checks whether the input string contains double quotes. If it does, then it decrements the count and updates the index to the index of the next double quote in that string (as shown in the above code segment). IfbReturnTokens
is false, then it decrements the count by the total number of nonsubsequent delimiters present in the input string.// return " "="" as="" token="" if="" consecutive="" delimiters="" are="" found.="" if="" (="" (sprevtoken.equals(sdelim))="" &&="" (stoken.equals(sdelim))="" )="" {="" sprevtoken="sToken;" itokenno++;="" return="" "";="" }="" check="" whether="" the="" token="" itself="" is="" equal="" to="" the="" delimiter="" if="" (="" (stoken.trim().startswith("\""))="" &&="" (stoken.length()="=" 1)="" )="" {="" this="" is="" a="" special="" case="" when="" token="" itself="" is="" equal="" to="" delimiter="" string="" snexttoken="oTokenizer.nextToken();" while="" (!snexttoken.trim().endswith("\""))="" {="" stoken="" +="sNextToken;" snexttoken="oTokenizer.nextToken();" }="" stoken="" +="sNextToken;" sprevtoken="sToken;" itokenno++;="" return="" stoken.substring(1,="" stoken.length()-1);="" }="" check="" whether="" there="" is="" a="" substring="" inside="" the="" string="" else="" if="" (="" (stoken.trim().startswith("\""))="" &&="" (!((stoken.trim().endswith("\""))="" &&="" (!stoken.trim().endswith("\"\""))))="" )="" {="" if="" (otokenizer.hasmoretokens())="" {="" string="" snexttoken="oTokenizer.nextToken();" check="" for="" presence="" of="" "\"\""="" while="" (!((snexttoken.trim().endswith("\""))="" &&="" (!snexttoken.trim().endswith("\"\"")))="" )="" {="" stoken="" +="sNextToken;" if="" (!otokenizer.hasmoretokens())="" {="" snexttoken="" ;="" break;="" }="" snexttoken="oTokenizer.nextToken();" }="" stoken="" +="sNextToken;" }="" }="">
The nextToken ()
metóda získava tokeny pomocou StringTokenizer.nextToken
a skontroluje, či je v tokene znak dvojitej úvodzovky. Ak metóda tieto znaky nájde, získa viac tokenov, kým nenájde žiadne s dvojitou úvodzovkou. Ukladá tiež token do premennej (sPrevToken
; pozri zdrojový kód) na kontrolu po sebe idúcich vystúpení oddeľovača. Ak nextToken ()
nájde po sebe idúce tokeny, ktoré sa rovnajú oddeľovaču, potom sa vráti ""
(reťazec s dĺžkou 0) ako token.
Podobne hasMoreTokens ()
metóda kontroluje, či je počet požadovaných tokenov menší ako celkový počet tokenov.
Ušetrite čas na vývoj
Tento článok vás naučil, ako ľahko napísať výkonný tokenizer. Pomocou týchto konceptov môžete rýchlo písať zložité tokenizátory, čo vám ušetrí značný čas na vývoj.
Bhabani Padhi je architekt a programátor v prostredí Java, ktorý v súčasnosti pracuje na vývoji webových a podnikových aplikácií pomocou technológie Java v austrálskom UniteSys. Predtým pracoval v spoločnosti Baltimore Technologies v Austrálii na vývoji produktov elektronickej bezpečnosti a v spoločnosti Fujitsu v Austrálii na projekte vývoja serverov EJB. Medzi záujmy spoločnosti Bhabani patrí vývoj distribuovaných počítačov, mobilných aplikácií a webových aplikácií pomocou technológie Java.Získajte viac informácií o tejto téme
- Získajte zdrojový kód tohto tipu
//images.techhive.com/downloads/idge/imported/article/jvw/2001/06/powerfultokenizer.java
- Viac informácií o BreakIterator
//java.sun.com/products/jdk/1.2/docs/api/java/text/BreakIterator.html
- Zobraziť všetky predchádzajúce Tipy pre Java a odovzdať svoje vlastné
//www.javaworld.com/javatips/jw-javatips.index.html
- Pre viac Úvodná úroveň články, navštívte JavaWorld 's Aktuálny index
//www.javaworld.com/javaworld/topicalindex/jw-ti-introlevel.html
- Naučte sa Java od základu v JavaWorld 's Java 101 stĺpec
//www.javaworld.com/javaworld/topicalindex/jw-ti-java101.html
- Odborníci na jazyk Java odpovedajú na vaše najťažšie otázky týkajúce sa jazyka Java v jazyku JavaWorld 's Java Q&A stĺpec
//www.javaworld.com/javaworld/javaqa/javaqa-index.html
- Zaregistrujte sa do JavaWorld tento týždeň bezplatný týždenný e-mailový bulletin a zistíte, čo je nové JavaWorld
//www.idg.net/jw-subscribe
Tento príbeh, „Java Tip 112: Improve tokenization of information-rich strings“, bol pôvodne publikovaný spoločnosťou JavaWorld.