Java StreamTokenizer 类
最后修改时间:2025 年 4 月 16 日
java.io.StreamTokenizer 类将输入流解析成标记。它可以识别数字、带引号的字符串和各种注释风格。这个类对于简单的词法分析任务很有用。
StreamTokenizer 将输入分解成标记,这些标记可以是单词、数字、字符串或特殊字符。它提供了配置哪些应被视为空白、注释或单词字符的方法。该类不是线程安全的。
StreamTokenizer 类概述
StreamTokenizer 将 InputStream 或 Reader 作为输入。它将标记分类为 TT_WORD、TT_NUMBER 或 TT_EOF 等类型。该类提供了配置标记识别规则的方法。
public class StreamTokenizer {
public StreamTokenizer(InputStream in);
public StreamTokenizer(Reader r);
public void resetSyntax();
public void wordChars(int low, int hi);
public void whitespaceChars(int low, int hi);
public void ordinaryChars(int low, int hi);
public void ordinaryChar(int ch);
public void commentChar(int ch);
public void quoteChar(int ch);
public void parseNumbers();
public void eolIsSignificant(boolean flag);
public void slashStarComments(boolean flag);
public void slashSlashComments(boolean flag);
public void lowerCaseMode(boolean fl);
public int nextToken();
public int ttype;
public String sval;
public double nval;
public int lineno();
}
上面的代码展示了 StreamTokenizer 的关键方法和字段。nextToken 方法读取下一个标记。标记类型存储在 ttype 中,字符串和数值存储在 sval 和 nval 中。
创建 StreamTokenizer
StreamTokenizer 可以从 InputStream 或 Reader 创建。 Reader 版本更适合字符流处理。在使用之前,该类需要配置才能定义标记识别规则。
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.StreamTokenizer;
public class Main {
public static void main(String[] args) {
try {
// Create from Reader
BufferedReader reader = new BufferedReader(new FileReader("data.txt"));
StreamTokenizer tokenizer1 = new StreamTokenizer(reader);
// Basic configuration
tokenizer1.wordChars('a', 'z');
tokenizer1.wordChars('A', 'Z');
tokenizer1.whitespaceChars(' ', ' ');
tokenizer1.whitespaceChars('\n', '\n');
tokenizer1.whitespaceChars('\r', '\r');
tokenizer1.whitespaceChars('\t', '\t');
System.out.println("StreamTokenizer created and configured");
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
此示例演示了如何从 Reader 创建 StreamTokenizer。我们将其配置为将字母识别为单词字符和常见的空白字符。完成后,始终关闭底层流。配置是标记化的必要条件。
基本标记化示例
StreamTokenizer 的最简单用法是读取标记,直到文件结束。每次调用 nextToken 都会返回标记类型。标记值存储在 sval(对于单词)或 nval(对于数字)中。
import java.io.StringReader;
import java.io.StreamTokenizer;
public class Main {
public static void main(String[] args) {
String input = "Hello 123 World 45.67";
StringReader reader = new StringReader(input);
StreamTokenizer tokenizer = new StreamTokenizer(reader);
try {
tokenizer.parseNumbers();
while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
switch (tokenizer.ttype) {
case StreamTokenizer.TT_WORD:
System.out.println("Word: " + tokenizer.sval);
break;
case StreamTokenizer.TT_NUMBER:
System.out.println("Number: " + tokenizer.nval);
break;
default:
System.out.println("Other: " + (char) tokenizer.ttype);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
此示例将包含单词和数字的简单字符串进行标记化。parseNumbers 方法启用数字识别。 switch 语句处理不同的标记类型。TT_EOF 表示输入流结束。
处理带引号的字符串
当使用 quoteChar 配置时,StreamTokenizer 可以识别带引号的字符串。整个带引号的字符串成为一个单独的标记。单引号和双引号都可以配置为引号字符。
import java.io.StringReader;
import java.io.StreamTokenizer;
public class Main {
public static void main(String[] args) {
String input = "Name 'John Doe' Age 25 City \"New York\"";
StringReader reader = new StringReader(input);
StreamTokenizer tokenizer = new StreamTokenizer(reader);
try {
// Configure single and double quotes as quote characters
tokenizer.quoteChar('\'');
tokenizer.quoteChar('"');
while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
if (tokenizer.ttype == '\'' || tokenizer.ttype == '"') {
System.out.println("Quoted string: " + tokenizer.sval);
} else if (tokenizer.ttype == StreamTokenizer.TT_WORD) {
System.out.println("Word: " + tokenizer.sval);
} else if (tokenizer.ttype == StreamTokenizer.TT_NUMBER) {
System.out.println("Number: " + tokenizer.nval);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
此示例演示了处理单引号和双引号字符串。带引号的内容可在 sval 中找到。引号字符本身作为标记类型返回。这允许区分不同的引号样式。
自定义标记识别
StreamTokenizer 提供了广泛的自定义,以确定构成标记的内容。您可以将字符范围定义为单词字符、空白或普通字符。resetSyntax 方法清除所有先前的设置。
import java.io.StringReader;
import java.io.StreamTokenizer;
public class Main {
public static void main(String[] args) {
String input = "user@example.com 192.168.1.1 #comment";
StringReader reader = new StringReader(input);
StreamTokenizer tokenizer = new StreamTokenizer(reader);
try {
// Reset and customize syntax
tokenizer.resetSyntax();
tokenizer.wordChars('a', 'z');
tokenizer.wordChars('A', 'Z');
tokenizer.wordChars('0', '9');
tokenizer.wordChars('@', '@');
tokenizer.wordChars('.', '.');
tokenizer.whitespaceChars(' ', ' ');
tokenizer.commentChar('#');
while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
if (tokenizer.ttype == StreamTokenizer.TT_WORD) {
System.out.println("Token: " + tokenizer.sval);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
此示例展示了自定义语法配置。我们将“@”和“.”作为单词字符来处理电子邮件和 IP。 “#”是注释字符。在 resetSyntax 之后,所有字符都是“普通字符”,直到配置为止。
跟踪行号
StreamTokenizer 可以在解析期间跟踪行号。lineno 方法返回当前的行号。这对于源代码处理中的错误报告很有用。
import java.io.StringReader;
import java.io.StreamTokenizer;
public class Main {
public static void main(String[] args) {
String input = "First line\nSecond line\nThird line";
StringReader reader = new StringReader(input);
StreamTokenizer tokenizer = new StreamTokenizer(reader);
try {
tokenizer.eolIsSignificant(true);
while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
if (tokenizer.ttype == StreamTokenizer.TT_EOL) {
System.out.println("End of line " + tokenizer.lineno());
} else if (tokenizer.ttype == StreamTokenizer.TT_WORD) {
System.out.println("Word at line " +
tokenizer.lineno() + ": " + tokenizer.sval);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
此示例演示了行号跟踪。eolIsSignificant(true) 使行尾标记具有意义。lineno 方法有助于识别标记位置。这对于编译器或解析器实现很有价值。
处理注释
StreamTokenizer 支持 C 风格(/* */)和 C++ 风格(//)的注释。slashStarComments 和 slashSlashComments 方法控制此行为。注释内容在标记化期间被跳过。
import java.io.StringReader;
import java.io.StreamTokenizer;
public class Main {
public static void main(String[] args) {
String input = "code /* comment */ more // line comment\nend";
StringReader reader = new StringReader(input);
StreamTokenizer tokenizer = new StreamTokenizer(reader);
try {
tokenizer.slashStarComments(true);
tokenizer.slashSlashComments(true);
while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
if (tokenizer.ttype == StreamTokenizer.TT_WORD) {
System.out.println("Token: " + tokenizer.sval);
} else if (tokenizer.ttype == StreamTokenizer.TT_EOL) {
System.out.println("End of line");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
此示例展示了 StreamTokenizer 中的注释处理。两种注释样式都被启用。标记器自动跳过注释内容。只有非注释标记由 nextToken 返回。
来源
在本文中,我们介绍了 Java StreamTokenizer 类的基本方法和特性。理解这些概念对于 Java 应用程序中的文本解析和词法分析至关重要。
作者
列出所有Java教程。