1. 序章

このチュートリアルでは、Java StreamTokenizerクラスを使用して文字のストリームをトークンに解析する方法を示します。

2. StreamTokenizer

StreamTokenizer クラスは、ストリームを1文字ずつ読み取ります。 それぞれに、次の属性を0個以上含めることができます:空白、アルファベット、数字、文字列引用符、またはコメント文字。

ここで、デフォルト構成を理解する必要があります。 次の種類の文字があります。

  • 単語文字:「a」から「z」および「A」から「Z」のような範囲
  • 数字:0,1、…、9
  • 空白文字:0から32までのASCII値
  • コメント文字:/
  • 文字列引用文字:’および“

行の終わりは個別のトークンとしてではなく空白として扱われることに注意してください。およびC/C++スタイルのコメントはデフォルトでは認識されません。

このクラスには、一連の重要なフィールドがあります。

  • TT_EOF –ストリームの終了を示す定数
  • TT_EOL –行の終わりを示す定数
  • TT_NUMBER –数値トークンを示す定数
  • TT_WORD –単語トークンを示す定数

3. デフォルト設定

ここでは、StreamTokenizerメカニズムを理解するための例を作成します。 このクラスのインスタンスを作成することから始め、 TT_EOF 値を返すまで、 nextToken()メソッドを呼び出します。

private static final int QUOTE_CHARACTER = '\'';
private static final int DOUBLE_QUOTE_CHARACTER = '"';

public static List<Object> streamTokenizerWithDefaultConfiguration(Reader reader) throws IOException {
    StreamTokenizer streamTokenizer = new StreamTokenizer(reader);
    List<Object> tokens = new ArrayList<Object>();

    int currentToken = streamTokenizer.nextToken();
    while (currentToken != StreamTokenizer.TT_EOF) {

        if (streamTokenizer.ttype == StreamTokenizer.TT_NUMBER) {
            tokens.add(streamTokenizer.nval);
        } else if (streamTokenizer.ttype == StreamTokenizer.TT_WORD
            || streamTokenizer.ttype == QUOTE_CHARACTER
            || streamTokenizer.ttype == DOUBLE_QUOTE_CHARACTER) {
            tokens.add(streamTokenizer.sval);
        } else {
            tokens.add((char) currentToken);
        }

        currentToken = streamTokenizer.nextToken();
    }

    return tokens;
}

テストファイルには、次のものが含まれています。

3 quick brown foxes jump over the "lazy" dog!
#test1
//test2

ここで、配列の内容を印刷すると、次のようになります。

Number: 3.0
Word: quick
Word: brown
Word: foxes
Word: jump
Word: over
Word: the
Word: lazy
Word: dog
Ordinary char: !
Ordinary char: #
Word: test1

例をよりよく理解するために、 StreamTokenizer.ttype StreamTokenizer.nval 、およびStreamTokenizer.svalフィールドについて説明する必要があります。

ttypeフィールドには、読み取ったばかりのトークンのタイプが含まれます。 かもしれない TT_EOF TT_EOL TT_NUMBER TT_WORD 。 ただし、引用符で囲まれた文字列トークンの場合、その値は引用符文字のASCII値です。 さらに、トークンが‘!’ のような属性のない通常の文字である場合、ttypeにはその文字のASCII値が入力されます。

次に、 svalフィールドを使用してトークンを取得します。これは、TT_WORD 、つまり単語トークンの場合のみです。 ただし、引用符で囲まれた文字列トークンを処理している場合(「lazy」など)、このフィールドには文字列の本文が含まれます。

最後に、 TT_NUMBERを使用して、数値トークンの場合にのみ、nvalフィールドを使用してトークンを取得しました。

4. カスタム構成

ここでは、デフォルトの構成を変更して、別の例を作成します。

まず、 wordChars(int low、int hi)メソッドを使用して、いくつかの追加の単語文字を設定します。 次に、コメント文字(’/’)を通常のにし、‘#’を新しいコメント文字として昇格させます。

最後に、 eolIsSignificant(boolean flag)メソッドを使用して、行の終わりをトークン文字と見なします。

streamTokenizerオブジェクトでこれらのメソッドを呼び出すだけで済みます。

public static List<Object> streamTokenizerWithCustomConfiguration(Reader reader) throws IOException {
    StreamTokenizer streamTokenizer = new StreamTokenizer(reader);
    List<Object> tokens = new ArrayList<Object>();

    streamTokenizer.wordChars('!', '-');
    streamTokenizer.ordinaryChar('/');
    streamTokenizer.commentChar('#');
    streamTokenizer.eolIsSignificant(true);

    // same as before

    return tokens;
}

そして、ここに新しい出力があります:

// same output as earlier
Word: "lazy"
Word: dog!
Ordinary char: 

Ordinary char: 

Ordinary char: /
Ordinary char: /
Word: test2

二重引用符がトークンの一部になったことに注意してください。改行文字は空白文字ではなく、通常の文字であるため、1文字のトークンです。

また、「#」文字に続く文字はスキップされ、「/」は通常の文字になります。

また、quoteChar(int ch)メソッドを使用して引用文字を変更したり、 whitespaceChars(int low、int hi)メソッドを呼び出して空白文字を変更したりすることもできます。 したがって、StreamTokenizerのメソッドをさまざまな組み合わせで呼び出してさらにカスタマイズすることができます。

5. 結論

このチュートリアルでは、 StreamTokenizerクラスを使用して、文字のストリームをトークンに解析する方法を見てきました。 デフォルトのメカニズムについて学び、デフォルトの構成で例を作成しました。

最後に、デフォルトのパラメーターを変更し、StreamTokenizerクラスの柔軟性に気づきました。

いつものように、コードはGitHubにあります。