`
liugang594
  • 浏览: 977472 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java中使用StreamTokenizer

 
阅读更多

按照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 StreamTokenizer使用

    注意:用JAVA解题一般用Scanner类来进行输入,但对时间要求严格的题,用它可能会超时,我、解POJ1823的时候遇到这样的问题,后改用StreamTokenizer类进行输入,过了。看来后者处理输入的效率要高点。  现小结如下...

    JAVA快速输入输出模板(StreamTokenizer)

    适合想用Java刷pat题的人,Java本身运行内存就大,所以特别容易超时,可以用StreamTokenizer来接收控制台数据

    java jdk实列宝典 光盘源代码

    java为数据结构中的列表定义了一个接口类java.util.list同时提供了3个实现类,分别是ArrayList、Vector、LinkedList使用; 生成不重复的随机数序列;列表、集合与数组的互相转换;java为数据结构中的映射定义一个接口...

    Thinking in 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 使用...

    Parsing-calculator:实现一个用于简单表达式的计算器。 使用java.io.StreamTokenizer和递归下降解析

    解析计算器实现一个用于简单表达式的计算器。 使用java.io.StreamTokenizer和递归下降解析

    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 编程入门思考

    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初学者入门教学

    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 JDK实例宝典

    13 使用StreamTokenizer统计文件的字符数 7. 14 序列化和反序列化对象 7. 15 控制对象的序列化和反序列 7. 16 读jar包的资源文件 7. 17 用Zip格式压缩和解压缩文件 7. 18 操作Excel文件 7....

    JAVA_Thinking in 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开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    本书是第II卷,以开发人员在项目开发中经常遇到的问题和必须掌握的技术为中心,介绍了应用Java进行桌面程序开发各个方面的知识和技巧,主要包括Java语法与面向对象技术、Java高级应用、窗体与控件应用、文件操作...

    JAVA_Thinking in Java(中文版 由yyc,spirit整理).chm

    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 使用...

    Think in Java(中文版)chm格式

    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 名字的可见性 ...

    Thinking in Java(中文版 由yyc,spirit整理).chm

    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 使用...

    ThinkInJava

    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 使用...

    thinkinjava

    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 使用...

Global site tag (gtag.js) - Google Analytics