按照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来接收控制台数据
`StreamTokenizer`是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 使用...
本文介绍了在ACM竞赛中使用Java的基础知识,包括输入输出的基本处理方法以及大数/高精度计算的实现。对于已经熟悉C/C++的选手而言,掌握这些知识将有助于他们在竞赛中更加高效地解决问题。接下来的文章中还将继续...
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....
`StreamTokenizer`是Java中用于将输入流转换为一系列可处理的“令牌”的类。这些令牌可以是单词、单个字符或者空白(包括注释)。它的主要作用在于帮助我们解析HTML文件中的各个元素,如标签、属性和文本内容。 - ...
通过对`java.io`包中的类和接口的学习,我们不仅能够深入了解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 使用...
- `StringBufferInputStream` 和 `StringOutputStream` 已在Java 1.5中废弃,不建议使用。 - `FileInputStream` 和 `FileOutputStream` 用于读写文件数据。 - `PipedInputStream` 和 `PipedOutputStream` 用于...
第4题要求创建一个名为`MyException`的自定义异常,并在`testException`类中使用它。 4. **条件判断和流程控制**: - 第1题中,根据考试成绩打印百分制分数段,可以使用switch语句实现。switch语句适用于基于特定...
本书是第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 使用...