按照Javadoc里的描述:StreamTokenizer
类获取输入流并将其解析为“标记”,允许一次读取一个标记。解析过程由一个表和许多可以设置为各种状态的标志控制。该流的标记生成器可以识别标识符、数字、引用的字符串和各种注释样式等。
简单的说就是一个可以将源代码文件解释成一个个标记的类,这些标记都对应不同的类别,例如数字,单词,行尾,末尾等。
本文中将使用以下源文件作为演示内容:
package com.iteye.liugang594.java.thread; import java.util.concurrent.CountDownLatch; public class TestCountDownLatch { private int number = 30; private long seconds = 40000L; /** * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { //create countdown final CountDownLatch countDownLatch = new CountDownLatch(10); for(int i = 0;i< 10;i++){ new Thread("Thread "+i){ public void run() { try { //wait countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(getName()+" started"); } }.start(); Thread.sleep(50); //count down countDownLatch.countDown(); } } }
一、提取数字
首先,看一下怎么提取以上内容中的数字,这里有以下几个:30,40000L, 10, 0, 10, 50。
StreamTokenizer tokenizer = new StreamTokenizer(reader); tokenizer.parseNumbers(); int nextToken = tokenizer.nextToken(); while(nextToken != StreamTokenizer.TT_EOF){ if(nextToken == StreamTokenizer.TT_NUMBER){ System.out.println("number "+ tokenizer.nval+" on line "+tokenizer.lineno()); } nextToken = tokenizer.nextToken(); }
打印结果:
number 30.0 on line 7 number 40000.0 on line 8 number 10.0 on line 17 number 0.0 on line 19 number 10.0 on line 19 number 0.0 on line 30 number 50.0 on line 31
有一个问题:在第30行上其实没有数字,却显示0.0,我觉得StreamTokenier的一个bug,它把终结符(也就是 } )后的点识别为一个数字。可以试着把其实的点删除,就可以得到正确答案。或者把点作为普遍的字符的对待,例如:
StreamTokenizer tokenizer = new StreamTokenizer(reader); tokenizer.parseNumbers(); tokenizer.ordinaryChar('.'); int nextToken = tokenizer.nextToken(); while(nextToken != StreamTokenizer.TT_EOF){ if(nextToken == StreamTokenizer.TT_NUMBER){ System.out.println("number "+ tokenizer.nval+" on line "+tokenizer.lineno()); } nextToken = tokenizer.nextToken(); }
二、删除注释
在示例源文件里有一些注释内容,这里演示一下怎么删除其中的注释:
StreamTokenizer tokenizer = new StreamTokenizer(reader); tokenizer.resetSyntax(); // reset all chars as ordinary char tokenizer.slashSlashComments(true); // recognize // tokenizer.slashStarComments(true); // recognize /**/ tokenizer.wordChars(Character.MIN_VALUE, Character.MAX_VALUE); // all chars will be considered as a part of word tokenizer.commentChar('/'); //set the comment char tokenizer.quoteChar('"'); // set quote char, this should be set, else the the / inside a string will be considered as comment int token = tokenizer.nextToken(); while (token != StreamTokenizer.TT_EOF) { // continue if not the end of file if(token == '"'){ //print " + content + " if we encounted a quote System.out.print((char)token); } if(tokenizer.sval != null){ // print token content if have System.out.print(tokenizer.sval); } if(token == '"'){ System.out.print((char)token); } token = tokenizer.nextToken(); }
注意:quote也需要被解析,否则 "//hello" 里的 //hello" 会被认为是注释而处理。
检查打印的内容,所有的注释都被删除,只留下源码主体部分。
三、字符串提取
和上节类似,这次只需要打印字符Token的内容:
StreamTokenizer tokenizer = new StreamTokenizer(reader); tokenizer.resetSyntax(); // reset all chars as ordinary char tokenizer.slashSlashComments(true); // recognize // tokenizer.slashStarComments(true); // recognize /**/ tokenizer.wordChars(Character.MIN_VALUE, Character.MAX_VALUE); // all chars will be considered as a part of word tokenizer.commentChar('/'); //set the comment char tokenizer.quoteChar('"'); int token = tokenizer.nextToken(); while (token != StreamTokenizer.TT_EOF) { // continue if not the end of file if(token == '"'){ System.out.println(tokenizer.sval); } token = tokenizer.nextToken(); }
注意,注释部分也需要包括到token中,否则注释里的字符串也会被解析,例如: // "hello world"
四、去除空行
去除空行可以将文件的大小进行压缩。例如用于网络传输的时候。以下代码片段可以用来去除空行:
StreamTokenizer tokenizer = new StreamTokenizer(reader); tokenizer.resetSyntax(); // remove all symbols before continue //assume all characters are words tokenizer.wordChars(Character.MIN_VALUE, Character.MAX_VALUE); //treat the new line as a token, this requires \r and \n should be white space tokenizer.eolIsSignificant(true); tokenizer.whitespaceChars('\r', '\r'); tokenizer.whitespaceChars('\n', '\n'); int nextToken = tokenizer.nextToken(); while(nextToken != StreamTokenizer.TT_EOF){ //print the content between lines if it's not empty if(nextToken != StreamTokenizer.TT_EOL){ if(tokenizer.sval != null && !"".equals(tokenizer.sval.trim())){ System.out.println(tokenizer.sval); } } nextToken = tokenizer.nextToken(); }
首先清除所有的标记,然后把Character范围内的值都认为是单词的一部分,然后设置换行符为一个Token,这里需要指定\r和\n为空格字符,以使得换行符起作用;然后在扫描的过程中,所在非换行符的内容如果为空字符串则跳过,否则打印。
相关推荐
注意:用JAVA解题一般用Scanner类来进行输入,但对时间要求严格的题,用它可能会超时,我、解POJ1823的时候遇到这样的问题,后改用StreamTokenizer类进行输入,过了。看来后者处理输入的效率要高点。 现小结如下...
适合想用Java刷pat题的人,Java本身运行内存就大,所以特别容易超时,可以用StreamTokenizer来接收控制台数据
java为数据结构中的列表定义了一个接口类java.util.list同时提供了3个实现类,分别是ArrayList、Vector、LinkedList使用; 生成不重复的随机数序列;列表、集合与数组的互相转换;java为数据结构中的映射定义一个接口...
2.2.3 Java中的数组 2.3 绝对不要清除对象 2.3.1 作用域 2.3.2 对象的作用域 2.4 新建数据类型:类 2.4.1 字段和方法 2.5 方法、自变量和返回值 2.5.1 自变量列表 2.6 构建Java程序 2.6.1 名字的可见性 2.6.2 使用...
解析计算器实现一个用于简单表达式的计算器。 使用java.io.StreamTokenizer和递归下降解析
2.2.3 Java中的数组 2.3 绝对不要清除对象 2.3.1 作用域 2.3.2 对象的作用域 2.4 新建数据类型:类 2.4.1 字段和方法 2.5 方法、自变量和返回值 2.5.1 自变量列表 2.6 构建Java程序 2.6.1 名字的可见性 2.6.2 使用...
2.2.3 Java中的数组 2.3 绝对不要清除对象 2.3.1 作用域 2.3.2 对象的作用域 2.4 新建数据类型:类 2.4.1 字段和方法 2.5 方法、自变量和返回值 2.5.1 自变量列表 2.6 构建Java程序 2.6.1 名字的可见性 2.6.2 使用...
2.2.3 Java中的数组 2.3 绝对不要清除对象 2.3.1 作用域 2.3.2 对象的作用域 2.4 新建数据类型:类 2.4.1 字段和方法 2.5 方法、自变量和返回值 2.5.1 自变量列表 2.6 构建Java程序 2.6.1 名字的可见性 2.6.2 使用...
13 使用StreamTokenizer统计文件的字符数 7. 14 序列化和反序列化对象 7. 15 控制对象的序列化和反序列 7. 16 读jar包的资源文件 7. 17 用Zip格式压缩和解压缩文件 7. 18 操作Excel文件 7....
2.2.3 Java中的数组 2.3 绝对不要清除对象 2.3.1 作用域 2.3.2 对象的作用域 2.4 新建数据类型:类 2.4.1 字段和方法 2.5 方法、自变量和返回值 2.5.1 自变量列表 2.6 构建Java程序 2.6.1 名字的可见性 2.6.2 使用...
本书是第II卷,以开发人员在项目开发中经常遇到的问题和必须掌握的技术为中心,介绍了应用Java进行桌面程序开发各个方面的知识和技巧,主要包括Java语法与面向对象技术、Java高级应用、窗体与控件应用、文件操作...
2.2.3 Java中的数组 2.3 绝对不要清除对象 2.3.1 作用域 2.3.2 对象的作用域 2.4 新建数据类型:类 2.4.1 字段和方法 2.5 方法、自变量和返回值 2.5.1 自变量列表 2.6 构建Java程序 2.6.1 名字的可见性 2.6.2 使用...
2.2.3 Java中的数组 2.3 绝对不要清除对象 2.3.1 作用域 2.3.2 对象的作用域 2.4 新建数据类型:类 2.4.1 字段和方法 2.5 方法、自变量和返回值 2.5.1 自变量列表 2.6 构建Java程序 2.6.1 名字的可见性 ...
2.2.3 Java中的数组 2.3 绝对不要清除对象 2.3.1 作用域 2.3.2 对象的作用域 2.4 新建数据类型:类 2.4.1 字段和方法 2.5 方法、自变量和返回值 2.5.1 自变量列表 2.6 构建Java程序 2.6.1 名字的可见性 2.6.2 使用...
2.2.3 Java中的数组 2.3 绝对不要清除对象 2.3.1 作用域 2.3.2 对象的作用域 2.4 新建数据类型:类 2.4.1 字段和方法 2.5 方法、自变量和返回值 2.5.1 自变量列表 2.6 构建Java程序 2.6.1 名字的可见性 2.6.2 使用...
2.2.3 Java中的数组 2.3 绝对不要清除对象 2.3.1 作用域 2.3.2 对象的作用域 2.4 新建数据类型:类 2.4.1 字段和方法 2.5 方法、自变量和返回值 2.5.1 自变量列表 2.6 构建Java程序 2.6.1 名字的可见性 2.6.2 使用...