Рубрики
Без рубрики

Руководство по StreamTokenizer

Узнайте, как анализировать поток символов с помощью StreamTokenizer.

Автор оригинала: Catalin Burcea.

1. введение

В этом уроке мы покажем, как разобрать поток символов на токены с помощью класса Java StreamTokenizer .

2. ПотокоКенизатор

Класс StreamTokenizer считывает поток символ за символом. Каждый из них может иметь ноль или более следующих атрибутов: пробел, алфавитный, числовой, строковый кавычок или символ комментария.

Теперь нам нужно понять конфигурацию по умолчанию. У нас есть следующие типы персонажей:

  • Символы слов : диапазоны от “a” до “z” и от “A” до ” Z
  • Числовые символы : 0,1,…,9
  • Символы пробела : Значения ASCII от 0 до 32
  • Символ комментария :/
  • Строковые символы кавычек : ‘и “

Обратите внимание, что концы строк обрабатываются как пробелы, а не как отдельные маркеры, и комментарии в стиле C/C++по умолчанию не распознаются.

Этот класс обладает набором важных полей:

  • TT_EOF – Константа, указывающая конец потока
  • TT_EOL – Константа, указывающая конец строки
  • TT_NUMBER – Константа, указывающая на числовой токен
  • TT_WORD – Константа, указывающая на маркер слова

3. Конфигурация по умолчанию

Здесь мы создадим пример, чтобы понять механизм StreamTokenizer . Мы начнем с создания экземпляра этого класса, а затем вызовем метод nextToken () , пока он не вернет значение TT_EOF :

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

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

    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 .

Поле type содержит тип только что прочитанного токена. Это может быть TT_EOF , TT_EL , TT_NUMBER , TT_WORD . Однако для токена строки в кавычках его значением является значение ASCII символа кавычки. Более того, если токен представляет собой обычный символ , такой как ‘!’ , без атрибутов, то тип | будет заполнен значением ASCII этого символа.

Далее, мы используем поле sval для получения токена, только если это TT_WORD , то есть токен слова. Но если мы имеем дело с токеном строки в кавычках – скажем, “ленивый”– , то это поле содержит тело строки.

Наконец, мы использовали поле для получения токена, только если это числовой токен, используя TT_NUMBER .

4. Пользовательская конфигурация

Здесь мы изменим конфигурацию по умолчанию и создадим другой пример.

Во-первых, мы собираемся установить некоторые дополнительные символы слов с помощью метода wordChars(int low, int hi) . Затем мы сделаем символ комментария (‘/’) обычным и продвинем ‘#’ в качестве нового символа комментария.

Наконец, мы рассмотрим конец строки как символ токена с помощью метода eolIsSignificant(логический флаг) .

Нам нужно только вызвать эти методы на объекте StreamTokenizer :

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

    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

Обратите внимание, что двойные кавычки стали частью токена, символ новой строки больше не является символом пробела, а обычным символом и, следовательно, односимвольным токеном.

Кроме того, символы, следующие за символом”#”, теперь пропускаются, а символ “/” является обычным символом.

Мы также могли бы изменить символ кавычки с помощью quoteChar(int ch) метода или даже пробелов, вызвав whitespaceChars(int low, int hi) метод. Таким образом, дальнейшие настройки могут быть сделаны, вызывая методы StreamTokenizer в различных комбинациях .

5. Заключение

В этом уроке мы видели, как разобрать поток символов на токены с помощью класса StreamTokenizer /. Мы узнали о механизме по умолчанию и создали пример с конфигурацией по умолчанию.

Наконец, мы изменили параметры по умолчанию и заметили, насколько гибок класс StreamTokenizer .

Как обычно, код можно найти на GitHub .