【问题标题】:Java Scanner Regex InputMistmastchExceptionJava 扫描器正则表达式 InputMistmastchException
【发布时间】:2016-01-23 12:19:24
【问题描述】:

我已经阅读了一些其他帖子,但无法弄清楚以下代码有什么问题以及为什么会引发异常:

public static void main(String[] args) {

    Scanner scanner = new Scanner(" 0 B 2 # L");

    String first = scanner.next("[0-9]+ [abB#]");
    String second = scanner.next("[0-9]+ [abB#] [LR]");

    System.out.println(first); 
    System.out.println(second);

}

预期输出:

0 B
2 # L

【问题讨论】:

    标签: java regex pattern-matching java.util.scanner delimiter


    【解决方案1】:

    引用Scanner.next(String)的javadoc:

    如果它与从指定字符串构造的模式匹配,则返回下一个标记。

    默认情况下(并且您没有更改),Scanner 将在空白处拆分令牌,因此 Scanner 返回的令牌是:

    "0"
    "B"
    "2"
    "#"
    "L"
    

    第一个next 令牌是"0",它与"[0-9]+ [abB#]" 不匹配,所以你得到InputMismatchException。

    解决方案

    不要使用Scanner。

    Pattern p = Pattern.compile(" *([0-9]+ [abB#]) +([0-9]+ [abB#] [LR]) *");
    Matcher m = p.matcher(" 0 B 2 # L");
    if (m.matches()) {
        System.out.println(m.group(1));
        System.out.println(m.group(2));
    }
    

    【讨论】:

    • 所以即使模式匹配包含一个空间来消耗字符串中的空间 java 已经标记了字符串以进行比较?
    • Java 没有,Scanner 有,如 next(String) 中所述,或者更确切地说,它还没有消耗任何东西。您可以尝试findInLine(String) 或findWithinHorizon(String, int),或者跳过使用Scanner 并使用正则表达式解析整个字符串。
    【解决方案2】:

    当使用Scanner 时,它会分隔整个输入。在您的情况下,它用空格分隔(默认):

    Scanner 使用分隔符模式将其输入分解为标记,默认情况下匹配空格。

    @Andreas 描述了异常的根本原因。

    现在,解决方案是使用忽略分隔符的方法。

    findInLine(java.lang.String)、findWithinHorizon(java.lang.String, int) 和 skip(java.util.regex.Pattern) 方法独立于分隔符模式运行。这些方法将尝试匹配指定的模式,而不考虑输入中的分隔符,因此可以在分隔符不相关的特殊情况下使用。

    你可以使用Scanner.findInLine:

    Scanner s = new Scanner(" 0 B 2 # L");
    String first = s.findInLine("[0-9]+ [abB#]"); // => 0 B
    System.out.println(first);
    String second = s.findInLine("[0-9]+ [abB#] [LR]"); // => 2 # L
    System.out.println(second);
    s.close(); 
    

    见IDEONE demo

    一个简单的Matcher 正则表达式解决方案:

    String str = " 0 B 2 # L";
    Pattern ptrn = Pattern.compile("[0-9]+ [abB#] [LR]|[0-9]+ [abB#]");
    Matcher matcher = ptrn.matcher(str);
    while (matcher.find()) {
        System.out.println(matcher.group(0));
    }
    

    见IDEONE demo

    较长的替代方案必须在较短的替代方案之前才能获得正确的匹配。

    【讨论】:

    • 这是我在原始解决方案中使用的,我只是不喜欢它解析字符串“0 q 2 # L”,例如首先匹配“2 #”,然后第二个匹配返回null,但如果这就是实现,那么我想这就是我需要使用它的方式
    • 我用一个简单的Matcher 正则表达式解决方案更新了我的答案。请注意替代方案的放置方式:长为第一,短为第二。
    猜你喜欢
    • 2015-06-26
    • 2012-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-07
    • 2012-01-06
    • 1970-01-01
    • 2014-10-31
    相关资源
    最近更新 更多