`
liugang594
  • 浏览: 987551 次
  • 性别: 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来接收控制台数据

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

    `StreamTokenizer`是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 使用...

    ACM java 基础

    本文介绍了在ACM竞赛中使用Java的基础知识,包括输入输出的基本处理方法以及大数/高精度计算的实现。对于已经熟悉C/C++的选手而言,掌握这些知识将有助于他们在竞赛中更加高效地解决问题。接下来的文章中还将继续...

    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编写HTML文件分析程序.pdf

    `StreamTokenizer`是Java中用于将输入流转换为一系列可处理的“令牌”的类。这些令牌可以是单词、单个字符或者空白(包括注释)。它的主要作用在于帮助我们解析HTML文件中的各个元素,如标签、属性和文本内容。 - ...

    java jdk io包类详解

    通过对`java.io`包中的类和接口的学习,我们不仅能够深入了解Java中基础输入输出流的实现原理,还能够掌握如何高效地处理文件和其他数据流。这对于日常的软件开发工作是非常有用的。此外,通过理解装饰者模式的应用...

    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 IO流读写

    - `StringBufferInputStream` 和 `StringOutputStream` 已在Java 1.5中废弃,不建议使用。 - `FileInputStream` 和 `FileOutputStream` 用于读写文件数据。 - `PipedInputStream` 和 `PipedOutputStream` 用于...

    java 上机题

    第4题要求创建一个名为`MyException`的自定义异常,并在`testException`类中使用它。 4. **条件判断和流程控制**: - 第1题中,根据考试成绩打印百分制分数段,可以使用switch语句实现。switch语句适用于基于特定...

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

Global site tag (gtag.js) - Google Analytics