java - StreamTokenizer 将 001_to_003 拆分为两个 token ;我怎样才能阻止它这样做?

标签 java string tokenize string-parsing

Java的StreamTokenizer在识别数字方面似乎过于贪婪。它的配置选项相对较少,而且我还没有找到让它执行我想要的操作的方法。以下测试通过,IMO 显示了实现中的一个错误;我真正想要的是将第二个标记识别为单词“20001_to_30000”。有任何想法吗?

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 代替,但它需要大量重构。

最佳答案

IMO,最好的解决方案是使用扫描仪,但如果您想强制古老的 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() 不适用于给定的标记。

关于java - StreamTokenizer 将 001_to_003 拆分为两个 token ;我怎样才能阻止它这样做?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4167872/

相关文章:

java - 换行符忽略正则表达式在 list 文件中查找包名称

java - 如何使用java监控托管服务器的堆大小

java - 在 Linux 上将 jpg 从一个文件夹复制到另一个文件夹

string - 在 Fortran 中,空字符串和未初始化的字符串有什么区别?

C++ 最大 std::string 长度由堆栈大小或堆大小决定?

python - 将作者字符串划分为作者

xslt - 为孙子中的每个标记复制 node() 并用 XSLT 1.0 中的标记替换孙子的元素文本?

java - Java 中的单例与 C++ 中的单例

C++,获取函数名

python - 你如何只从 python 日期时间中提取日期?