Java StreamTokenizer将001_到003拆分为两个令牌;我如何防止它这样做?
Java的StreamTokenizer似乎过于贪婪地识别数字。它的配置选项相对较少,我还没有找到一种方法让它实现我想要的功能。以下测试通过,IMO显示实现中存在错误;我真正想要的是第二个标记被识别为一个单词“20001到30000”。有什么想法吗Java StreamTokenizer将001_到003拆分为两个令牌;我如何防止它这样做?,java,string,tokenize,string-parsing,Java,String,Tokenize,String Parsing,Java的StreamTokenizer似乎过于贪婪地识别数字。它的配置选项相对较少,我还没有找到一种方法让它实现我想要的功能。以下测试通过,IMO显示实现中存在错误;我真正想要的是第二个标记被识别为一个单词“20001到30000”。有什么想法吗 public void testBrokenTokenizer() throws Exception { final String query = "foo_bah 20001_to_30000"; StreamTo
public void testBrokenTokenizer()
throws Exception
{
final String query = "foo_bah 20001_to_30000";
StreamTokenizer tok = new StreamTokenizer(new StringReader(query));
tok.wordChars('_', '_');
assertEquals(tok.nextToken(), StreamTokenizer.TT_WORD);
assertEquals(tok.sval, "foo_bah");
assertEquals(tok.nextToken(), StreamTokenizer.TT_NUMBER);
assertEquals(tok.nval, 20001.0);
assertEquals(tok.nextToken(), StreamTokenizer.TT_WORD);
assertEquals(tok.sval, "_to_30000");
}
FWIW我可以改用StringTokenizer,但这需要大量重构。在我看来,最好的解决方案是使用扫描仪,但如果您想强制古老的StreamTokenizer为您工作,请尝试以下方法:
import java.util.regex.*;
...
final String query = "foo_bah 20001_to_30000\n2.001 this is line number 2 blargh";
StreamTokenizer tok = new StreamTokenizer(new StringReader(query));
// recreate standard syntax table
tok.resetSyntax();
tok.whitespaceChars('\u0000', '\u0020');
tok.wordChars('a', 'z');
tok.wordChars('A', 'Z');
tok.wordChars('\u00A0', '\u00FF');
tok.commentChar('/');
tok.quoteChar('\'');
tok.quoteChar('"');
tok.eolIsSignificant(false);
tok.slashSlashComments(false);
tok.slashStarComments(false);
//tok.parseNumbers(); // this WOULD be part of the standard syntax
// syntax additions
tok.wordChars('0', '9');
tok.wordChars('.', '.');
tok.wordChars('_', '_');
// create regex to verify numeric conversion in order to avoid having
// to catch NumberFormatException errors from Double.parseDouble()
Pattern double_regex = Pattern.compile("[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?");
try {
int type = StreamTokenizer.TT_WORD;
while (type != StreamTokenizer.TT_EOF) {
type = tok.nextToken();
if (type == StreamTokenizer.TT_WORD) {
String str = tok.sval;
Matcher regex_match = double_regex.matcher(str);
if (regex_match.matches()) { // NUMBER
double val = Double.parseDouble(str);
System.out.println("double = " + val);
}
else { // WORD
System.out.println("string = " + str);
}
}
}
}
catch (IOException err) {
err.printStackTrace();
}
本质上,您正在从StreamTokenizer卸载数值的标记化。正则表达式匹配是为了避免依赖NumericFormatException来告诉您Double.parseDouble()在给定标记上不起作用。我怀疑这就是大多数语言禁止标识符中的第一个字符为数字的原因。。。