百度、CSDN了很多资料解释的都不够详细,有些地方甚至模糊不清,学不会java.io.StreamTokenizer类的基本使用方法。因此,综合了一些CSDN和GitHub上用该类类型写的代码,自己在本地测试。总结,试图摸索怎么使用该类。在原有的解释上面用自己的理解加以补充。本文的错误是一定不会少的,恳请各位批评指正。
首先是 按照Javadoc里的描述:StreamTokenizer 类获取输入流并将其解析为“标记”,允许一次读取一个标记。解析过程由一个表和许多可以设置为各种状态的标志控制。该流的标记生成器可以识别标识符、数字、引用的字符串和各种注释样式等。
关键点:
- 类java.io.StreamTokenizer可以获取输入流并将其分析为Token(标记)。StreamTokenizer的nextToken方法将读取下一个标记
- 默认情况下,StreamTokenizer认为下列内容是Token:字母、数字、除C和C++注释符号以外的其他符号。如符号“/”不是Token,注释后的内容也不是,而“”是Token。单引号和双引号以及其中的内容,只能算是一个Token。
- 要统计文件的字符数,不能简单地统计Token数,因为字符数不等于Token,按照Token的规定,引号中的内容就算是10页也算是一个Token。如果希望引号和引号中的内容都算作Token,应该通过StreamTokenizer的ordinaryCha方法将单引号和双引号当做普通字符处理。
StreamTokenizer中的基本方法:
- commenChar(int ch) - 指定某个字符为注释字符,此字符之后直到行结尾都被stream tokenizer忽略。
- eolIsSignificant(boolean flag) - 决定一个行结束符是否被当作一个基本的符号处理,如果是true,则被当作一个基本符号,不当作普通的分隔符,如果是false,则保持原义,即当作普通的分隔符。
- lineno() - 返回当前流所在的行号。
- lowerCaseMode(boolean flag) - 决定是否读取一个单词时是否转变成小写。
- nextToken() - 分析下一个。
- ordinaryChar(int ch) - 指定字符在这个tokenizer中保持原义,即只会把当前字符认为普通的字符,不会有其他的语义。
- ordinaryChars(int low, int hi) - 指定范围内的字符保持语义,同上
- parseNumbers() - 当stream tokenizer遭遇到一个单词为双精度的浮点数时,会把它当作一个数字,而不是一个单词。
- pushBack() - 回退,会引起下一个nextToken方法返回当前值。
- quoteChar(int ch) - 指定当前字符为当前tokenizer中的分隔符,在两个符号之间被当作一个字符串解析。
- resetSyntax() - 重置语法表使所有的字符都被认为是“ordinary”。
- slashSlashComments(boolean flag) - 如果为true,则之间的都被认为是注释,反之,不是。
- slashStartComments(boolean flag) - 如果为true,则//之后到行结尾的所有都被认为是注释,反之,不是。
- whitespaceChars(int low, int hi) - 字符low与hi之间的所有字符都被当作为空格符,即被认识为tokenzier的分隔符。
- wordChars(int low, int hi) - 字符low与hi之间的所有字符都被当作为单词的要素。 一个单词是由一个单词要素后面跟着0个或者更多个单词要素或者数字要素。
以上都是从网上和他人的博客上得到的资料,我认为如果要理解StreamTokenizer,其中有一些值得注意的点:Token,WORD(单词),单词要素,NUMBER(数字),分隔符。
经过本地测试,我的总结如下:
- 默认情况下,StreamTokenizer认为下列内容是Token:①除C和C++注释符号以外的其他符号,②字母,③数字。
- Token是一个int数据类型,其中读取到的NUMBER用-2表示,WORD用-3表示,EOF(流结束符号)用-1表示,其余读到的符号都用ASCII码表示。可以用以下四个StreamTokenizer的静态成员变量判断Token读到的是什么。
- 默认情况下,单词(WORD)与单词、单词与数字(NUMBER)、数字与数字之间都用分隔符来划分。一旦Token读取到一个字母,其后的若干个字母(称为单词要素)和数字(称为数字要素)都被当作该单词的要素;一旦Token读取到一个数字,其后的所有数字都被当作该数字的数字要素。如:当读取“a123 abc+123”时,会认为是读取到了4个Token,分别为 -3,-3,43,-2。再往后读就全是-1。
- 具体读取到的的WORD或NUMBER,可以通过StreamTokenizer对象.sval、StreamTokenizer对象.nval获得。
- 行结尾换行符号('n')忽视,即你不会读到一个Token为('n')。
- 如果一行是abc 实际是abcrn eol其实是n.可以调用方法tokenizer.eolIsSignificant(true)使其可以被读取为一个Token,而不是分隔符,此时Token得到的值就是10(10是'n'的ASCII码)。这时候就可以通过Token==StreamTokenizer.TT_EOL判断是否读到了换行符。 PS:同理你可以通过Token==StreamTokenizer.TT_WORD判断是否读取到单词;抑或是Token==(int)'+'来判断是否读取到了+号。
- 可以通过调用类方法来改变默认设置。
测试代码框架如下:
import java.io.*;
public class Test {
private static StreamTokenizer st;
private static int token;
public static void main(String[] args) throws IOException {
FileReader filePath = new FileReader("This is the file path.");
st = new StreamTokenizer(new BufferedReader(filePath));
st.eolIsSignificant(true);
getToken();
while (token!=StreamTokenizer.TT_EOF){
//your operation
switch (token){
case -2:
System.out.println(st.nval);
break;
case -3:
System.out.println(st.sval);
break;
default:
System.out.println(token);
}
getToken();
}
}
private static void getToken() throws IOException
token = st.nextToken();
}



