我试图解析包含电子邮件地址的文档,但是StreamTokenizer将电子邮件地址分为两个单独的部分。
我已经将@
符号设置为ordinaryChar
,并将空格设置为唯一的whitespace
:
StreamTokenizer tokeziner = new StreamTokenizer(freader);
tokeziner.ordinaryChar('@');
tokeziner.whitespaceChars(' ', ' ');
尽管如此,所有电子邮件地址仍被拆分。
要解析的行如下所示:
"Student 6 Name6 LastName6 [email protected] Competition speech University of Innsbruck".
标记器将
[email protected]
分为"del6"
和"uni.at"
。有没有办法告诉 token 生成器不要在
@
符号处拆分? 最佳答案
所以这就是为什么它像以前那样工作:StreamTokenizer
将其输入视为编程语言标记器。即,根据程序员为其设置的语法,将其分解为“单词”,“数字”,“带引号的字符串”,“注释”等的标记。程序员告诉它哪些字符是文字字符,普通字符,注释字符等。
因此,实际上,它确实进行了相当复杂的标记化-识别注释,带引号的字符串,数字。请注意,在一种编程语言中,您可以拥有一个类似于a = a+b;
的字符串。一个简单的 token 生成器(仅用空格将文本拆分)会将其拆分为a
,=
和a+b;
。但是StreamTokenizer
会将其分解为a
,=
,a
,+
,b
和;
,并且还将为您提供每个 token 的“类型”,因此您的“语言”解析器可以将标识符与运算符区分开。 StreamTokenizer
的类型相当基本,但是此行为是了解您的情况的关键。
它没有将@
识别为空格。实际上,它正在解析它并将其作为 token 返回。但是它的值在ttype
字段中,您可能只是在看sval
。StreamTokenizer
将您的行识别为:
学生一词
数6.0
单词Name6
姓氏LastName6
单词del6
人物 @
uni.at一词
竞争一词
言语一词
大学一词
的字
因斯布鲁克一词
(这是我编写的一个小样例的实际输出,该样例标记了您的示例行并按类型打印)。
实际上,通过告诉@
是一个“普通字符”,您就是在告诉它将@
当作自己的 token (无论如何默认情况下都会这样做)。 ordinaryChar()
documentation告诉您该方法:
指定此分词器中的字符参数为“普通”。
它删除了角色作为注释的任何特殊含义
字符,单词组成部分,字符串定界符,空格或数字
字符。 当解析器遇到这样的字符时,
解析器将其视为单字符 token ,并将ttype字段设置为
字符值。
(我的重点)。
实际上,如果您改为像wordChars()
那样将其传递给tokenizer.wordChars('@','@')
,它将把整个电子邮件保持在一起。我添加的小演示给出了:
学生一词
数6.0
单词Name6
姓氏LastName6
单词[email protected]
竞争一词
言语一词
大学一词
的字
因斯布鲁克一词
如果您需要类似编程语言的标记器,StreamTokenizer
可能适合您。否则,您的选择取决于您的数据是否基于行(每行是一个单独的记录,每行上可能会有不同数量的 token ),在这种情况下,您通常会从读取器中逐行读取行,然后拆分它们使用String.split()
,或者如果它只是用空格分隔的 token 链,那么Scanner
可能更适合您。