Lese tekst ord for ord ved hjelp av en StringTokenizer

Merknad I ny kode anbefales det å bruke String-klassens split-metode eller en Scanner for å splitte opp tekst i enkeltkomponenter. En innføring i hvordan dette kan gjøres er beskrevet i notatet Splitte opp tekst i enkeltkomponenter. Bruk av StringTokenizer-objekter karakteriseres som foreldet. Klassen er fortsatt med i klassebiblioteket for å sikre kompatibilitet bakover.

Når det blir lest inn tekst til et javaprogram, kan det noen ganger være behov for å splitte opp den innleste teksten i flere enkeltkomponenter, for eksempel i enkelte ord. Et objekt av type StringTokenizer kan brukes til å foreta en slik oppsplitting. En enkelt komponent av en tekststreng kalles på engelsk for token. Det forklarer navnet på klassen StringTokenizer. Vi må importere klassen fra pakken java.util.

Når vi oppretter et StringTokenizer-objekt, må vi som konstruktørparameter bruke den tekststrengen (det vil si String-objektet) som vi ønsker å splitte opp. Det betyr blant annet at vi må opprette et nytt StringTokenizer-objekt for hver tekststreng som vi ønsker å splitte opp. Dersom vi ikke bestemmer noe annet, så er det bare såkalt white-space som regnes som skille mellom enkeltkomponentene. Med white-space menes det mellomrom (det vil si blanke tegn), tabulatortegn og tegn for linjeskifte. Med dette alternativet vil eventuelle andre skilletegn, slik som komma, punktum, spørsmålstegn, etc., bli regnet som en del av det ordet som de står rett bak. Vi har imidlertid mulighet til å spesifisere andre tegn som skille mellom komponentene, ved at vi som en ekstra konstruktørparameter bruker en tekstreng som inneholder alle de tegn vi ønsker skal oppfattes som skille. For eksempel vil tekststrengen "., " spesifisere punktum, komma og blanktegn (mellomrom) som skille mellom enkeltkomponentene. Det som regnes som white-space, er på tilsvarende måte definert av strengen " \t\n\r".

Eksempler

  String tekst;
  < tilordne verdi til tekst, for eksempel
          ved innlesing fra tastatur eller fil >
  StringTokenizer t1 = new StringTokenizer(tekst);
  //bare white-space vil nå bli regnet som skille mellom enkeltkomponentene.

  StringTokenizer t2 = new StringTokenizer(tekst, ",.!; \t\n\r");
  //komma, punktum, utropstegn og semikolon vil i tillegg til white-space
  //bli regnet som skille mellom enkeltkomponentene (ordene).

Dersom vi har opprettet et StringTokenizer-objekt som vist i eksemplene, så vil følgende metoder være de mest aktuelle å bruke for å foreta selve oppsplittingen i enkeltord eller komponenter:

  String nesteOrd = t1.nextToken(); //returnerer neste komponent i tekst
  boolean flere = t1.hasMoreTokens(); //returnerer true i tilfelle det er
           //flere ord (komponenter) igjen, returnerer false ellers
  int antall = t1.countTokens(); //returnerer antall komponenter

Programeksempel

I programmet Forfatternavn.java som er gjengitt nedenfor, blir det fra tekstfeltet input lest inn navn på formatet
Etternavn, Fornavn (eventuelt et eller flere mellomnavn).
Navnene skrives ut igjen i tekstfeltet output på formatet
Fornavn (eventuelt et eller flere mellomnavn) Etternavn.
Eksempel: Innlest navn
Beauvoir, Simone de
blir skrevet ut igjen som
Simone de Beauvoir
I programmet er navnene kalt forfatternavn, men det kan selvsagt være hvilke som helst andre navn på samme format. Driverklasse for programmet finnes i fila Tokentest.java

Innlesing, konvertering og utskrift av navn skjer i metoden konverterNavn(). Den splitter opp det innleste navn ved hjelp av en StringTokenizer der komma og mellomrom oppfattes som skille mellom ordene. Først trekkes etternavnet ut av den innleste strengen og lagres i en egen variabel. Deretter trekkes det ut fornavn og eventuelle mellomnavn så lenge det finnes flere. De tilføyes etter tur i en egen variabel for fornavn og mellomnavn. Til slutt blir strengen som inneholder etternavnet tilføyd, og det hele vises i tekstfeltet for utskrift. For øvrig blir det mellom de enkelte navnene lagt inn mellomrom.

public class Forfatternavn extends JFrame
{
  private JTextField input, output;

  public Forfatternavn()
  {
    super( "Forfatternavn" );
    input = new JTextField( 30 );
    output = new JTextField( 30 );
    output.setEditable( false );
    Container c = getContentPane();
    c.setLayout( new FlowLayout() );
    c.add( new JLabel( "Forfatternavn (ettenavn, fornavn):" ) );
    c.add( input );
    c.add( new JLabel( "Forfatternavn (fornavn etternavn):" ) );
    c.add( output );
    input.addActionListener( new Inputlytter() );
    setSize( 600, 100 );
    setVisible( true );
  }

  public void konverterNavn()
  {
    String navn = input.getText();
    StringTokenizer leser = new StringTokenizer( navn, ", " );
    String etternavn = "";
    if ( leser.hasMoreTokens() )
      etternavn = leser.nextToken();
    String fornavn = "";
    while ( leser.hasMoreTokens() )
      fornavn += leser.nextToken() + " ";

    if ( !etternavn.equals( "" ) )
      output.setText( fornavn + " " + etternavn );
    else
      output.setText( "Ingen navn lest inn." );
  }

  private class Inputlytter implements ActionListener
  {
    public void actionPerformed( ActionEvent e )
    {
      if ( e.getSource() == input )
        konverterNavn();
    }
  }
}

Mulighet for å få også skilletegn oppfattet som komponenter

Dersom vi ikke bestemmer noe annet, vil de spesifiserte skilletegnene mellom komponentene ikke bli returert i form av enkeltkomponenter ('tokens') når vi bruker metoden nextToken. Dette gjelder både når vi bruker default-alternativet med white-space som skilletegn, og når vi har spesifisert skilletegnene med en ekstra konstruktørparameter. Vi kan imidlertid oppnå å få også skilletegnene returnert som komponenter ('tokens') dersom vi tilføyer true som parameter når vi oppretter StringTokenizer-objektet (vi må i så fall også ha parameter som inneholder ønskede skilletegn):

  String s = < en eller annen tekst >;
  String skilletegn = < streng som inneholder ønskede skilletegn >;
  StringTokenizer t = new StringTokenizer( s, skilletegn, true );
  //t.nextToken() vil nå også returnere skilletegnene som token. De vil bli
  //returnert enkeltvis med lengde 1, selv om det finnes flere av dem
  //etter hverandre.

Copyright © Kjetil Grønning og Eva Hadler Vihovde, revidert 2014