1. Въведение
В този урок ще покажем как да анализираме поток от символи в маркери, използвайки класа Java StreamTokenizer .
2. StreamTokenizer
Класът 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 .
Полето ttype съдържа типа на току-що прочетения маркер. Може да е TT_EOF , TT_EOL , TT_NUMBER , TT_WORD . Обаче за кодиран символен низ неговата стойност е стойността ASCII на символа на кавичката. Освен това, ако символът е обикновен знак като „!“ , без атрибути, тогава ttype ще се попълни със стойността ASCII на този символ.
След това използваме sval поле, за да получим маркера, само ако това е TT_WORD , т.е. Но ако имаме работа с котиран символен низ - кажете „мързелив“ - тогава това поле съдържа тялото на низа.
И накрая, използвахме полето nval, за да получим маркера, само ако това е цифров маркер, използвайки 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.